C知识点总结结构体指针使用
- 格式:doc
- 大小:504.50 KB
- 文档页数:4
位操作:熟悉& | ^ << >>操作。应聘嵌入式C开发的岗位会考这方面的知识。见实验5。
结构体共用体
如前面讲的,作为函数参数和返回值,结构体是值传递。结构体变量之间可以直接赋值,结构体在初始化时才能整体赋值。
C99里新的结构体初始化方法。初始化结构体的指定成员变量。见《C primer plus》P382 struct book{char a; int b; double c }; struct book surprise ={ .b=3 };即初始化指定的成员变量b,其他成员变量的值赋值为0。在内核驱动代码中会经常见到。
指向结构体的指针及使用
struct node { int data; struct node *next; } node1;
struct node *point=&node1;
内存模型
高地址Array [ point ] ----- > node1
此时,point指向node1。即*point和node1对应的是同一块内存。
(*point).data等价于node1.data对应的是同一块内存。
(*point).next等价于node1.next对应的是同一块内存。即黄色背景的内存。
point->next
为什么这段代码行得通:
int offset= &( ( (struct book*) 0 )->b); //获得成员变量b在结构体的偏移量。
等价于:struct book *ptr=NULL; int offset= & ( ptr->b) ; // &(*ptr).b ;
编译器维护关于每个结构类型的信息,指示每个字段的字节偏移。它以这些偏移作为存储器引用指令中的移位,从而产生对结构元素的引用的代码。结构体的各个字段的选取完全是在编译时处理的。参考《深入理解》P166页中的一个例子。
程序对内存的访问,都是先生成该内存的地址,再访问该内存。
结构体对齐,及填充
结构体的对齐与填充
C语言标准未严格规定该如何对齐,不同系统的对齐策略略有不同。
参考《深入理解》P170数据对齐。
linux策略:linux/IA32 (Intel Architecture 32)下,基本类型按其占用字节大小对齐。(即该类型变量的首地址能被sizeof(类型)整除,基本类型是指泛整形和浮点类型)。
结构体按其最大成员变量的对齐规则对齐。若结构体按n个字节对齐,那么结构体的大小也要能被n整除。
结构体内的成员按上图的方式对齐。
struct S{ int a; char b; }; 该结构体按其最大成员int的对齐规则对齐。
结构体struct S 按4个字节对齐,即它的首地址和大小必须都能被4整除。
因为有对齐的要求就出现了内存填充(空着若干个字节,不使用)。
A
B
C
D
E
3.42
如何尽量避免填充带来的分析影响:结构体定义按成员对齐规则从大到小书写,这样填充只会在尾部填充。当然,逻辑关系的考虑也很重要。
位域:整形类型(一般用unsigned int)
不能对结构体里的位字段取地址。
判断一个char ch=0x12字节内位序
共用体:首地址对齐。
判断系统是否为大端
指向函数的指针及库函数的使用:exit atexit
《C语言495个问题》1.36 4.12
枚举类型的使用:对一类宏的整体定义。
struct week{Sunday, };
使用库函数进行文件操作:缓冲区设置函数,文件操作库函数的使用。
学习对这些函数的使用时,请同学们参考《apue》第五章,这里会告诉大家函数的优点、缺点。比谭浩强的书描述要准确。
文件流:是全缓冲的。可以使用fseek进行位置移动。
标准输入输出流:是行缓冲的。不可以使用fseek等移动读写位置
标准错误输出流:是不缓冲的。不可以使用fseek等移动读写位置。P110
标准库函数区分文本文件和二进制文件。但在linux系统里并不对这两种文件区分,所以,在linux环境下,指定字符b作为type的一部分实际上不起作用。P113 const、volatile等限定符
restrict:是c99才支持的,形参指针用restrict修饰的函数,告诉编译器在该函数内只通过这一个指针引用他所指的内存。这样,编译器就可以对该指针的操作进行代码优化。编
译时需要在gcc后面加-std=c99
volatile:用该符号限定变量,告诉编译器每次使用到该变量值的时候,都要从存储它的位置重新取它的值。对于那些值容易变化的变量,需要加这个限定符。通常用在多线程编程中,嵌入式的硬件寄存器。
restrict和volatile都是为了方便编译器进行代码优化。
volatile int i=3; movl $3 -4(%ebp) ;
int b=i; movl -4(%ebp) %eax; movl %eax -8(%ebp);
int c=i; movl -4(%ebp) %eax ; movl %eax -12(%ebp)