register
这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内存寻址访问以提高效率
register 变量必须是能被 CPU 寄存器所接受的类型。意味着 register 变量必须是一个单个的值,并且其长度应 <= 整型的长度。而且 register 变量可能不存放在内存中,所以不能用取址运算符“&” 来获取 register 变量的地址
static
含义1:表示退出一个块后仍然存在的局部变量(延长生命周期)
含义2:表示不能被其它文件访问的全局变量和函数
sizeof
在计算变量所占空间大小时,括号可以省略,【sizeof(variable)或sizeof variable】而计算类型大小时不能省略【sizeof(int)】
sizeof是关键字,define不是关键字
signed char 与 unsigned char
ASCII码的取值:0-127,故两种char类型表示ASCII字符时存储都一致。额外的取值(-128 -- -1,128-255)暂无意义。
当从char整形提升时,unsigned char高位补0,signed char高位补1,(如printf (“%d %x”, c, c );)
const
在C语言中,const修饰的变量 只读,但还是变量
volatile
告诉编译器 variable是随时可能发生变化的,每次使用它的时候必须从内存中取出variable的值(防止编译器错误优化)
struct
空结构体的大小就定位 1个byte
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构体中的柔性数组成员前面必须至少一个其他成员
例:typedef struct st_type { int i; int a[]; }type_a;
type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int))
此时再用 sizeof(*p)测试结构体的大小,发现仍然为 4【柔性数组不是结构体正式成员】
union
所有的数据成员共用一个空间,只配置一个足够大的空间以来容纳最大长度的数据成员,成员默认public
大端模式(Big_endian):数据的高字节存储在低地址中,而低字节则存放在高地址中。【符号位的判定固定为第一个字节,容易判断正负】
小端模式(Little_endian):数据的高字节存储在高地址中,低字节则存放在低地址中。【强制转换数据不需要调整字节内容】
typedef
typedef int int32; unsigned int32 j = 10;错误:typedef不支持类型扩展,它不是简单的替换(define)
typedef int* pint; const pint p1; pint const p2;
p1, p2都是 int* const
#define PCHAR char*
PCHAR p3,p4; // p4是char
注释
int/*...*/i; 编译器用空格代替注释
//Is it a \
valid comment? 需要换行时可以用 \
C语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符自动接续到前一行,但是注意:反斜杠之后不能有空格。
预编译
一.条件编译:使得我们可以按不同的条件去编译不同的程序部分
如:#ifdef … #else #endif
#if… #elif… #else #endif
二.编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译【格式:#error …(没有双引号)】
三.#pragma message(“消息文本”)
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来
内存对齐
结构体(或联合体)的数据成员,第一个数据成员放在offset(偏移量)为0的地方,以后每个数据成员的对齐 按照 对齐值和这个数据成员自身长度中比较小的一个进行
结构体(或联合体)本身也要进行对齐,对齐将按照对齐值和结构(或联合)最大数据成员长度中,比较小的那个进行
【某些硬件平台只能在某些地址处取某些特定类型的数据;加快处理器访问速度】
默认#pragma pack(4)【对齐值4字节】
位段(位域)
有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可,位域技术就是在成员变量所占用的内存中选出一部分位宽来存储数据。只有有限的几种数据类型可以用于位域成员
位段成员所占比特位数:1~其本身类型的最大位长。
位段成员可以没有名字,无名位段表示该空间不用。
位段成员不能进行取地址的“&”运算。
#与##
#x表示将宏参数转换为字符串
#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x)));
SQR(8)à The square of 8 is 64【在字符串中包含宏参数】
x##y表示将前后两部分合起来
#define XNAME(n) x ## n
XNAME(6)à x6
小tip
循环嵌套控制在 3 层以内
switch-case分支 把正常情况放在前面,而把异常情况放在后面
枚举变量是int类型
不用的指针置空,每次使用指针前要assert(NULL != p),assert是一个宏,只在Debug模式下作用
在一个函数体内,变量定义与函数语句之间要加空行,逻辑联系密切处不加空行