《C与指针》读书笔记
1.结构基础知识
结构是一些值的集合,这些值成为它的成员。
1.1 结构声明
struct tag {member-list} varialbe-list;
下面是结构的声明示例:
(1)简单声明
struct {
int a;
char b;
float c;
} x;
(2)使用tag。
struct SIMPLE {
int a;
char b;
float c;
};
struct SIMPLE x;
(3)使用typedef。
typedef struct SIMPLE {
int a;
char b;
float c;
}Simple;
Simple x;
1.2 结构成员
结构成员也可以是标量、数组、指针甚至是其他结构。
struct COMPLEX {
float f;
int a[20];
long *lp;
struct SIMPLE s;
struct SIMPLE sa[10];
struct SIMPLE *sp;
};
1.3 结果成员的直接访问
结构变量的成员是通过点操作符(.)进行访问的。
struct COMPLEX comp;
comp.sa[4].c
1.4 结构成员的间接访问
如果拥有一个指向结构的指针,可以通过(->)间接访问到结构成员。
struct COMPLEX *cp;
cp->f
cp->a
cp->s
1.5 结构的自引用
使用结构指针作为结构自身的成员可以实现结构的自引用
struct SELF_REF {
int a;
struct SELF_REF* b;
int c;
}
1.6 不完整的声明
解决结构互相依赖存在的问题。
struct B;
struct A {
struct B *partner;
};
struct B {
struct A *partner;
}
1.7 结构的初始化
struct INIT_EX {
int a;
short b[10];
Simple c;
} x = {
10,
{1,2,3,4,5},
{25,'x',1.9}
};
2 结构、指针和成员
typedef sturct {
int a;
short b[2];
} Ex2;
typedef sturct EX{
int a;
char b[3];
Ex2 c;
struct EX *d;
} Ex;
Ex x = {10,"Hi",{5,{-1,25}},0};
Ex *px = &x;
上面声明和初始化在内存中的表示:
2.1 访问指针
(1)px的右值
(2)px的左值
2.2 访问结构
(1)*px的右值
(2)*px 的左值
2.3 访问结构成员
(1)px->a的右值
(2)px->b的右值
(3)px->b[1]的右值
2.4 访问嵌套的结构
(1)px->c的左值
(2)px->c.a的右值
(3)*px->c.b的右值
2.5 访问指针成员
px->d->a
px->d->b
px->d->c
px->d->c.a
px->d->c.b[1]
3.结构的存储分配
编译器按照成员列表的顺序一个接一个地给每个成员分配内存。只有当存储成员需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外的内存空间。
struct ALIGN {
char a;
int b;
char c;
};
这样声明的空间利用率低。
struct ALIGN {
int b;
char a;
char c;
}
这样声明占8个字节,比前面的声明节省了33%。
4. 作为函数参数的结构
typedef struct {
char product[PRODUCT_SIZE];
int quantity;
float unit_price;
float total_amount;
} Transaction;
直接把结构作为参数传递给一个函数;
void prite_receipt(Transaction trans);
不过这样做效率比较低,程序必须把结构复制一遍。而且如果函数希望修改到结构的成员时,这个函数无法满足。所以更高效的做法是把传递给函数一个结构的指针。函数可以通过间接访问访问到每个成员。也可以修改到结构成员。
void prite_receipt(Transaction* trans);
5. 位段
位段的声明和结构类似,但它的成员是一个或多个位的字段。位段成员必须声明为int,singed int或unsigned int类型。
下面是一个位段声明的例子:
struct CHAR {
unsigned ch : 7;
unsigned font : 6;
unsigned size : 19;
};
struct CHAR ch1;
这个声明取自一个文本格式化程序,它可以处理多达2^7个字符、2^6种不同的字体以及2^19个单位的长度。位段可以节省存储空间。
6. 联合
联合的声明和结构类似,但它的行为却和结构不同。联合的所有成员引用的是内存中的相同位置。当你想在不同的时刻把不同的东西存储于同一个位置时,就可以使用联合。
union {
float f;
int i;
} fi;
可以将fi解释成float,也可以解释成int。
6.1联合的初始化
联合变量可以被初始化,但这个初始值必须是联合第1个成员的类型,而且它必须在一对花括号里面。
union {
int a;
float b;
char c[4];
} x = {5};
把 x.a 初始化为5。