面试题(1)
1、关键字sizeof
sizeof是一个关键字,其作用是返回一个对象或者类型所占的内存字节数,对绝大多数编译器而言,返回值为无符号整形数据。需要注意的是,使用sizeof获取数组长度时,不要对指针应用sizeof操作符,比如下面的例子:
1. void ClearRAM(char array[]) 2. { 3. int i ; 4. for(i=0;i<sizeof(array)/sizeof(array[0]);i++) //这里用法错误,array实际上是指针 5. { 6. array[i]=0x00; 7. } 8. } 9. 10. int main(void) 11. { 12. char Fle[20]; 13. 14. ClearRAM(Fle); //只能清除数组Fle中的前四个元素 15. }
我们知道,对于一个数组array[20],我们使用代码sizeof(array)/sizeof(array[0])可以获得数组的元素(这里为20),但数组名和指针往往是容易混淆的,有且只有一种情况下数组名是可以当做指针的,那就是数组名作为函数形参时,数组名被认为是指针,同时,它不能再兼任数组名。注意只有这种情况下,数组名才可以当做指针,但不幸的是这种情况下容易引发风险。在ClearRAM函数内,作为形参的array[]不再是数组名了,而成了指针。sizeof(array)相当于求指针变量占用的字节数,在32位系统下,该值为4,sizeof(array)/sizeof(array[0])的运算结果也为4。所以在main函数中调用ClearRAM(Fle),也只能清除数组Fle中的前四个元素了。
2、优先级
3、编译器的一些小知识
1) 默认情况下,char类型的数据项是无符号的,所以它的取值范围是0~255;
2) 在所有的内部和外部标识符中,大写和小写字符不同;
3) 通常局部变量保存在寄存器中,但当局部变量太多放到栈里的时候,它们总是字对齐的。
4) 压缩类型的自然对齐方式为1。使用关键字__packed来压缩特定结构,将所有有效类型的对齐边界设置为1;
5) 整数以二进制补码形式表示;浮点量按IEEE格式存储;
6) 整数除法的余数的符号于被除数相同,由ISO C90标准得出;
7) 如果整型值被截断为短的有符号整型,则通过放弃适当数目的最高有效位来得到结果。如果原始数是太大的正或负数,对于新的类型,无法保证结果的符号将于原始数相同。
8) 整型数超界不引发异常;像unsigned char test; test=1000;这类是不会报错的;
9) 在严格C中,枚举值必须被表示为整型。例如,必须在‑2147483648 到+2147483647的范围内。但MDK自动使用对象包含enum范围的最小整型来实现(比如char类型),除非使用编译器命令‑‑enum_is_int 来强制将enum的基础类型设为至少和整型一样宽。超出范围的枚举值默认仅产生警告:#66:enumeration value is out of "int" range;
10) 对于结构体填充,根据定义结构的方式,keil MDK编译器用以下方式的一种来填充结构:
I> 定义为static或者extern的结构用零填充;
II> 栈或堆上的结构,例如,用malloc()或者auto定义的结构,使用先前存储在那些存储器位置的任何内容进行填充。不能使用memcmp()来比较以这种方式定义的填充结构!
11) 编译器不对声明为volatile类型的数据进行优化;
12) __nop():延时一个指令周期,编译器绝不会优化它。如果硬件支持NOP指令,则该句被替换为NOP指令,如果硬件不支持NOP指令,编译器将它替换为一个等效于NOP的指令,具体指令由编译器自己决定;
13) __align(n):指示编译器在n 字节边界上对齐变量。对于局部变量,n的值为1、2、4、8;
14) __attribute__((at(address))):可以使用此变量属性指定变量的绝对地址;
15) __inline:提示编译器在合理的情况下内联编译C或C++ 函数;