常问关键字
1.continue
语句的作用是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环。注意:continue语句并没有使整个循环终止。
2.break
会使最近包含break语句跳出;
在while for、循环中 跳出本层循环;
在swich-case中跳出对应的case;
如果for(){switch case: break},for循环不受影响;
break 语句用在循环体中,可结束本层循环,continue语句用在循环体中,可结束本次循环
3.volatile
作用:告诉编译器该变量是容易发生变化的,不能对该变量进行优化,每次取值都必须从内存中取值而不是直接去取之前在寄存器中的值
例子:
volatile int a = 20, b, c;
b = a;
c = a;
代码执行流程如下
b = a; 先从a的内存中取值存放到寄存器,再把寄存器的值给存到b的内存
c = a; 把寄存器的值给存到c的内存
可以看出编译器对c=a这步进行优化,不再执行从a的内存中取值,而是直接从寄存器中取值,如果这段时间内a的发生变化,那么c就不能得到最新的值,这个时候就需要使用volatile告诉编译器,不要对变量a优化,每次都是从内存中取a的值
常见场景:
1)多线程使用共享变量:因为多线程是多核操作,同时进行
2)中断:中断程序会修改其他程序中使用的变量
3)硬件寄存器:因为寄存器随时会被修改,好比AD转换的寄存器,随时会因 为电压变化而修改
4)外部任务会修改变量
4.class和struct
1)继承权限:class是默认private,struct是public
2)访问权限:class作为对象的实现体,默认是私有访问,而struct是作为数据结构的实现体,是公有访问
3)class可以用于定义模板,而struct不能
5.union
联合体union和结构体struct的区别:
对于联合体所有的成员都共享一块内存,而结构体是所有变量内存的叠加,需要考虑字节对齐问题,对于联合体来说,只要你修改里面的成员的数据就会修改其他成员的数据,而结构体的成员数据是不影响的
联合体一般可以用来判断大小端问题:
大端字节:高字节存放在低位地址,低字节存放在高地址
小端字节:低字节存放在低位,高字节存放在高位
使用联合体判断大小端问题的例子:
union my
{
short t;
char b[2];
};
typedef union my MY;
int main()
{
MY test;
test.t=0X0102;
if(test.b[0]==0x01 && test.b[1]==0x02)
{
printf("这是大端字节序\n");
printf("%x\n",test.b[0]);
printf("%x\n",test.b[1]);
}
if(test.b[0]==0x02 && test.b[1]==0x01)
{
printf("这是小端字节序\n");
printf("%x\n",test.b[0]);
printf("%x\n",test.b[1]);
}
return 0;
}
大小端转换问题:
这里主要是位移操作
比如对于一个32位进行大小端转换:
思路:把0-7位移动到24-31,8-15位移动到16-23,16-23位移动到 8-15位,24-31位移动到0-7
//32位大小端交换
int swap(int value)
{
value=((value & 0x000000ff)<<24)|
((value & 0x0000ff00)<<8)|
((value & 0x00ff0000)>>8)|
((value & 0xff000000)>>24);
return value;
}
计算占用空间大小问题:
对于不同位的操作系统,个别数据类型数据大小不一样,
long 和unsigned long在32位中是4个字节
在64位中是8个字节
计算的时候需要考虑字节对齐问题:
1)所占空间必须是成员变量中字节最大的整数倍
2)每个变量类型的偏移量必须是该变量类型的整数倍
3)对于联合体,由于所有变量都是共用一块内存,还需注意数组占用最大内存
6.typedef与define
#define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。
typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。
注意#define和typedef定义指针的区别
#define myptr int* p
myptr a,b;//a是int * a, b是 int b
typedef int* myptr;
myptr a,b;//a是int * a, b是 int* b
// 补充:int *p,q表示p是指针变量,q是int变量
7.const
1)定义变量,表示该变量是个常量,不允许修改
例如:const int a = 100; a = 200; // 报错
2)修饰函数参数,表示函数体内不能修改该参数的值
3)修饰函数的返回值 const char getstr()
4)const修饰函数在c++的类中不能是虚函数
5)const 修饰的变量存放位置
对于const修饰的局部变量:存放在栈中,代码结束就会释放,在C语言中可以通过指针修改里面的值
对于const修饰的全局变量(已初始化的)存放在只读数据段,不可以通过指针修改里面的值,未出示化的存放在.bss
8.static
1.定义变量
静态全局变量---->作用域只能作用域本文件,每次函数调用该变量都会被初始化
静态局部变量----->生命周期不会随函数结束结束,直到程序结束,但是在函数外面不能使用该变量,只能在函数中使用,该变量是有记忆的,会记住上次的值,该变量只被初始化一次
对于这两种变量来说,如果初始化的会在数据段内,未初始化的在.bss段或者初始化为0,这两种变量都会在程序结束才会释放,只不过作用域不同,静态局部变量只限定于函数中,但是该函数结束,该变量并没有被干掉,静态全局变量限定于本文件中
9.sizeof
1.sizeof()和strlen()的区别
首先sizeof是关键字,strlen是函数,sizeof用来计算占用内存大小,strlen是用来计算字符串的长度,特别是对于需不需要包含’\0’问题:sizeof是需要给\0计算空间的,strlen是不需要,sizeof是在编译的时候计算的,而strlen是在运行的时候计算
2.求指针大小
在32位机器下,对于sizeof(指针变量)都是4个字节,比如
int *a;
sizeof(a); //4
3.计算数组大小
//sizeof计算的是数组的大小即数据类型*[]
//strlen计算的是字符串长度
int num[5]={1,2,3,4};
printf("%ld\n",sizeof(num));//20
char str[10]={"hello"};
printf("%ld\n",strlen(str));//5
printf("%ld\n",sizeof(str));//10