这是我面试过程中常被问到的问题,都是自己整理的希望对你们有帮助。
常见基本类型的字节大小
32位操作系统
char :1个字节(固定)
*(即指针变量): 4个字节(32位机的寻址空间是4个字节。同理64位编译器)(变化*)
short int : 2个字节(固定)
int: 4个字节(固定)
unsigned int : 4个字节(固定)
float: 4个字节(固定)
double: 8个字节(固定)
long: 4个字节
unsigned long: 4个字节(变化*,其实就是寻址控件的地址长度数值)
long long: 8个字节(固定)
1.指向字符串常量的指针,指向字符串的常量指针(const)
const char* p = "hello"; // 指向 "字符串常量"
p[0] = 'X'; // 错误! 想要修改字符串的第一个字符. 但是常量不允许修改
p = p2; // 正确! 让p指向另外一个指针.
char* const p = "hello"; // 指向字符串的" 常量的指针"
p[0] = 'X'; // 正确! 允许修改字符串, 因为该字符串不是常量
p = p2; // 错误! 指针是常量, 不许修改p的指向
char const * 和 const char* 是一样的. const 的位置在char左边还是右边都一样.
常量指针的const应当写在 *星号的右边.
指向常量字符串的常量指针的写法是 const char* const p = "xx"; 要2个const
2.typedef & #define的问题
有下面两种定义pStr数据类型的方法,两者有什么不同?哪一种更好一点?
typedef char* pStr;
#define pStr char*;
分析:通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:
typedef char* pStr1;
#define pStr2 char *
pStr1 s1, s2;
pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。上例中define语句必须写成 pStr2 s3, *s4; 这这样才能正常执行。
3.const的问题
(1)可以定义const常量,具有不可变性。
例如:const int Max=100; int Array[Max];
(2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
例如: void f(const int i) { .........} 编译器就会知道i是一个常量,不允许修改;
(3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。
如(1)中,如果想修改Max的内容,只需要:const int Max=you want;即可!
(4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错;
例如: void f(const int i) { i=10;//error! }
(5)可以节省空间,避免不必要的内存分配。 例如:
#define PI 3.14159 //常量宏
const doublePi=3.14159; //此时并未将Pi放入RAM中 ......
doublei=Pi; //此时为Pi分配内存,以后不再分配!
double I=PI; //编译期间进行宏替换,分配内存
double j=Pi; //没有内存分配
double J=PI; //再进行宏替换,又一次分配内存!
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
(6)提高了效率。
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
- sizeof与strlen的区别:
char str[20]="0123456789";
int a=strlen(str); // a=10;strlen 计算字符串的长度,以\0'为字符串结束标记。
int b=sizeof(str); // b=20;sizeof 计算的则是分配的数组str[20] 所占的内存空间的大小,不受里面存储的内容影响.
上面是对静态数组处理的结果,如果是对指针,结果就不一样了
char* ss = "0123456789";
sizeof(ss)结果4===》ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,应该是长整型的,所以是4,sizeof(*ss) 结果1===》*ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,是char类型的,占了1位strlen(ss)= 10如果要获得这个字符串的长度,则一定要使用 strlen
Sizeof结构体为结构体中定义的数据类型的总的空间(注意字节对齐)。
Sizeof对union为union中定义的数据类型的最大数据类型的大小。
5 .auto, register, static分析
auto即C语言中局部变量的默认属性,编译器默认所有的局部变量都是auto的,定义的变量都是在栈中分配内存。
static关键字指明变量的“静态”属性,同时具有“作用域限定符”的意义,修饰的局部变量存储在程序静态区,static的另一个意义是文件作用域标示符。
static修饰的全局变量作用域只是声明的文件中,static修饰的函数作用域只是声明的文件中
register关键字指明将变量存储于寄存器中,register只是请求寄存器变量,但不一定请求成功。register变量的必须是CPU寄存器可以接受的值,不能用&运算符获取register变量的地址,这样使用的好处是处理快。
6. const, volatile同时修饰变量
(1) “编译器一般不为const变量分配内存,而是将它保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作。”
(2) volatile的作用是“告诉编译器,i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值”。 &nb