读书人

编程语言学习札记:C语言 (3) 复合数据

发布时间: 2012-08-29 08:40:14 作者: rapoo

编程语言学习笔记:C语言 (3) 复合数据类型
int a[4];static char daytab[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};func(int a[4]) {...} /* 可写作: */func(int a[]) {...}func(int *a) {...} /* 指针类型为指向int类型的指针 */func(char daytab[2][13]) {...} /* 可写作: */func(char daytab[][13]) {...}func(char (*daytab)[13]) {...} /* 指针类型为指向大小为13的char类型数组的指针 */struct [name] { type a; type b; ...} [var1, var2, ...];?

struct point { /* 结构声明 */ int x; int y;};struct point pt; /* 结构声明 */struct rect { /* 嵌套结构声明 */ struct point pt1; struct point pt2;} screen = {0, 0, 3, 2}; /* 初始化,对于初值是简单变量或字符串并且无空值的情况,内层的花括号可以省略 */int x = screen.pt1.x; /* 访问结构成员;相同的变量和成员名称不冲突 */?

结构可以作为一个整体复制和赋值,可以用 sizeof varsizeof(type)?

注意结构的长度不一定是个成员的长度之和,因为在内存中存储时,不同的类型有不同的对齐要求,结构中可能存在空穴。使用 #define LEN (sizeof apt / sizeof(struct point))struct point apt[] = {0, 0, 1, 1, 2, 2, 3, 3};size_t alen = LEN;?

预处理器不对类型名进行分析,但是预处理器不计算 struct node { char *key; struct node *left; struct node *right;};?

还有一种两个结构相互引用的变体。

struct t {    /* ... */    struct s *p;};struct s {    /* ... */    struct t *q;};
?typedef int Length; /* 定义整型Length */typedef char *String; /* 定义字符指针类型String */typedef struct node *Tree; /* 定义结构指针类型Tree */typedef struct node { char *key; Tree left; Tree right;} Treenode; /* 定义结构类型Treenode *//* 定义函数指针类型Func,该函数有两个char *类型参数,返回int类型值 */typedef int (*Func)(char *, char *);?

注意 union utag { int ival; float fval; char *sval;} u, *up;u.ivalup->fval?

对于联合的成员,读取的类型必须是最近一次存入的类型。可以把联合理解为一个所有成员相对于基地址的偏移量都为0的结构,该结构空间足够容纳最“宽”的成员,并且其对齐方式适合于联合中所有类型的成员。

对联合允许的操作和对结构允许的操作相同,可以作为一个整体单元进行赋值、复制、取地址和访问其中一个成员。

联合只能用其第一个成员类型的值进行初始化。

struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1;} flags;?

冒号后的数字表示字段的宽度,用二进制位数表示。单个字段的引用方式和其他结构成员相同。

字段是否能覆盖字边界由具体的实现定义。字段可以不命名,无名字段(只有一个冒号和宽度)起填充作用。特殊宽度0可以用来强制在下一个字边界上对齐。

字段的分配是平台相关的,所以在使用时要考虑到移植性的问题。字段不是数组,并且没有地址,不能对它们使用 & 运算符。

原文