关键字
volatile
编译时,不进行优化。如一些特殊的变量在中断时会被修改,为了保证每次都从该变量的地址中读取。
如
volatile int i = 10;
int j = i;
.....
int k = i;
在省略号中,对于i没有改变,但是k=i这一步还是会从i的地址中读取数据。如果没有volatile,则k=i这一步会将上次i的数值放到k中,而不是从i的地址中读取。
const
定义常量,如果一个变量被const修饰,它的值不能改变。
- 作用:
1、预编译指令#define只是对值进行简单的替换,不能进行类型检查;
2、保护被修饰的东西,防止意外修改,增强程序的健壮性;
3、将const修饰的变量放在符号表中,称为编译期间的常量,没有了存储和读内存的操作,效率高。
- 用法
1、修饰局部变量
const int i = 5;
int const i = 5;
两种写法相同,需要给变量初始化,之后无法修改。
const char * str = "fasdaddf";
有const修饰,如果后期修改内容,则会报错。如str[4] = ‘x’;
2、常量指针和指针常量
const int * n;
或者
int const * n;
常量指针(在星号左边)说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的;也可以改变指针的值。
int * const n;
指针常量(在星号右边)的指针地址不能改变,但是地址指向的数值可以改变。
其他作用可以上网查阅。
static
修饰函数或者变量。
1、隐藏功能
static修饰的函数和变量,在其他文件中不可见。
也就是说在不同文件中,用static可以定义相同名字的变量,也不能通过extern来调用其他文件中的函数或者变量。
2、保持变量的持久
3、默认初始化为0
全局变量也具有该效果。
static和const变量的存放位置
①static无论是全局变量还是局部变量都存储在全局/静态区域,在编译期就为其分配内存,在程序结束时释放。
②const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放;const局部变量存储在栈中,代码块结束时释放。
③全局变量存储在全局/静态区域,在编译期为其分配内存,在程序结束时释放。
④局部变量存储在栈中,代码块结束时释放。
restrict
C99标准引入,只可以用于限定和约束指针,表明该指针释放问一个数据对象的唯一且初始的方式。即告诉编译器,所有修改该指针指向内存中内容的操作必须通过该指针来修改,不能通过其他途径(其他变量或者指针)修改
char * strcpy(char *restrict,const char *restrict)
struct
结构体
- 结构体对齐问题
两条原则:
(1)结构体成员的偏移量必须是该成员大小的整数倍
(2)结构体大小必须是所有成员大小的整数倍
计算方法
(1)根据原则(1)进行偏移量和长度计算
(2)根据原则(2)进行长度的补齐,如长度18,补长到20使得是所有成员大小的整数倍
其他注意点:
(1)数组的大小被拆分成数组元素的大小,即char x[5]则为5个char,而不是大小为5bytes的数组
例子
(1)例子1
// 满足两个原则,得到大小为8bytes
struct s1{
char ch1;//偏移量0
char ch2;//偏移量1
int i;//偏移量4,因为int长度为4bytes
}
(2)例子2
// 满足两个原则,得到大小为12bytes
struct s2{
char ch1;//偏移量0
int i;//偏移量4
char ch2;//偏移量8
//由于偏移量8,长度为9,不是4bytes(int)倍数,则得到12bytes
}
(3)包含数组的结构体例子3
// 满足两个原则,得到大小为20bytes
struct s3{
char ch1;//偏移量0
int i;//偏移量4
char str[10];//偏移量8,且相当于10个char
//由于偏移量8,长度为18,不是4bytes(int)倍数,则得到20bytes
}
(4)包含结构体的结构体例子4
// 满足两个原则,得到大小为20bytes
struct s4{
char ch1;//偏移量0
int i;//偏移量4
struct s{//结构体被当做两个元素——ch2和j,而不是一个8bytes的整体
char ch2;//偏移量8
int j;//偏移量12
}
float f;//偏移量16,4bytes长度
//由于偏移量16,长度为20,则得到20bytes
}
(5)包含联合体的结构体例子5
// 满足两个原则,得到大小为20bytes
struct s5{
char ch1;//偏移量0
int i;//偏移量4
union s{//联合体被当做一个整体
char ch2;//偏移量8
int j;//偏移量12
}
//由于偏移量16,长度为20,则得到20bytes
}
(6)指定对齐值的结构体例子6
// 满足两个原则,得到大小为20bytes
//如果没有指定对齐值,则结构体大小是24,因为double长度为8bytes,20不是8的倍数
//如果指定了对齐长度4,则结构体大小是20bytes,是4的倍速
//如果成员对齐值和指定对齐值选择小的作为对齐值,例如制定对齐值10,最大成员长度8,则最终和8对齐
#pragma pack(4) //指定向4对齐
struct s6{
char ch;//偏移量0
int i;//偏移量4
float f;//偏移量8
double d;//偏移量12,长度8bytes
}
欢迎关注我的微信公众号
互联网矿工