495-51-60
51.如何向接受结构参数的函数传入常量值?怎样创建无名的中间的常量的结构值?
答:传统的C语言没有办法生成匿名的结构值。你必须使用临时结构或一个小的结构生成函数。
C99标准引入了“复合字面量”,复合字面量的一种形式就可以允许结构常量。例如,向假定的plotpoint函数传入一个坐标对常量,可以调用
plotpoint ((struct point)(1, 2));
与“指定初始值”结合,也可以用成员名称确定成员值:
plotpoint ((struct point)(x = 1, y = 2));
52.怎样从/向数据文件读/写结构
答:用fwrite()编写一个结构相对简单:
fwrite(&somestruct, sizeof somestruct, 1, fp);
对应的fread调用可以再把它读回来,此处fwrite收到一个结构的指针并把这个结构的内存映像作为字节流写入文件(或在对应的fread的时候读入)。sizeof操作符计算出结构占用的字节数。
只要范围内有fwrite的原型(通常只需包含<STDIO.H>),那么ANSI编译器下这样调用fwrite就是正确的,在ANSI之前的编译器中,需要对第一个参数进行类型转换:
fwrite((char *)somestruct, sizeof somestruct, 1, fp);
重要的是fwrite接受字节指针,而不是结构指针。
但是这样用内存映像写出的书奴文件却不能移植,尤其是当结构中包含浮点成员或指针的时候,结构的内存布局跟机器和编译器都有关,不同的编译器可能使用不同数量的填充位,不同机器上基本类型的大小和字节顺序也不尽相同,因此,作为内存映像写出的结构在别的机器上(甚至是被别的编译器编译后)不一定能被读回来,当你需要在不同的机器上交换数据文件的时候,尤其要注意。
53.结构充填
为什么我的编译器在结构中留下了空洞?这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉充填,或者控制结构域的对齐方式?
答:当内存中的值合理对齐时,很多机器都能非常高效地访问。例如,在按字节寻址的机器中,2字节的short int型变量必须放在偶地址上,而4字节的long int型变量则必须存放在4的整数倍地址上。某些机器甚至根本就不能访问没有对齐的地址,因此必须要求所有的数据都正确地对齐
假如你声明了这个结构:
struct
{
char c;
int i;
};
编译器通常都会在char和int之间留出一个没有命名也没有使用的空洞,以确保int型域正确对齐。(根据最保守的对齐要求,结构本身也是对齐的,因此第二个域可以根据第一个域的位置进行累进对齐,编译器保证它所分配的结构对齐,对malloc也是如此)
编译器可能提供某种扩展用于控制结构的填充
如果你真的那么在意被浪费的空间,可以把结构中的域按从大到小的顺序排列,以最大限度地降低充填的影响,数组成员应该根据它的元素类型大小而不是整个数组的大小进行排序的时候,使用位域也可以很好地控制大小和对齐,但是这样也有它的缺点。
3.为什么sizeof返回的值大于结构大小的期望值,是不是尾部有充填
答:为了确保分配连续的结构数组时正确对齐,结构可能有这种尾部