开源项目Tinyhttpd第二篇 详解sizeof关键字
Tinyhttpd 接上一篇文章,接下来我们要注意的关键字是sizeof。sizeof在我的印象里都是一个用来返回某个数据类型所占的内存,然而前段时间被人家问到了基本用法,都忘了。。。。所以写出来整理一下。 1.普通用法
- sizeof(type)/sizeof var_name sizeof是以字节形式给出了所操作数据的大小。前一种的格式都喜闻乐见,而后一种对我来说很少见,当用这种格式时主要是用来操作变量和对象,但是如果是操作一个类型必须要添加括号。但是由这里也可以看出来sizeof并不是函数!!!!因为一个正常的函数是需要加括号的。 而且sizeof也不是一种操作符!!!!,为什么这么说呢,可以看下面的例子:
int a=0;
cout<<sizeof(a=4)<<endl;
cout<<a<<endl;
这段程序的输出结果为:
4
0
在当初在其他大佬的博客上看到这段程序时,我发现这个东西真的好迷,因为我认为答案是4和3,后来把sizeof看作是一种编译预处理就想的过去了,因为显然在sizeof处理阶段显然括号内并没有编译,而是被替换成类型int。
- sizeof不能用来操作未知存储大小的数据类型,未知内容的结构和联合类型,void类型。例如:
sizeof(max);//int max()
sizeof(char_v);//char char_v[MAX],MAX未赋值
sizeof(void);
以上用法全都是错误的!!! 以上用法全都是错误的!!! 以上用法全都是错误的!!!
- sizeof的基本用法 上面的这些7788的东西,说出来没有什么依据,下面通过一些常用的用法来认识sizeof的用法:
sizeof(char);/sizeof(signed char)/sizeof(unsigned char)
sizeof(p);//int *p或者string *p或者char*********
sizeof(a);//int a[10]
sizeof(b);//char b[]="hello";
1和2的结果都是1,不管是什么类型,sizeof后的结果都是取决于操作系统的,在32位操作系统上面就是4,在64位上就是8,sizeof(a)在这里等价于数组长度乘以sizeof(int),换句话说:sizeof(a)=10*sizeof(int)。sizeof(b)等于6,原因是因为字符串后面一般都会有个”\0”,这个。。。预编译符会算进去的!!!!!
int b[20]={3,4};
char c[2][3]={"aa","bb"};
sizeof(b);\\20*4
sizeof(c);\\6
以上的例子可以看的出来sizeof的值并不取决于赋值的情况,数组的大小取决于它在编译时被分配的空间,也就是各维度乘以数组元素的大小。
- 函数的sizeof使用方法 sizeof并不能测量整个函数占用的内存大小!!!!而是测量数组返回值类型的大小。但是要在这期间注意不能对返回值类型为空或者仅仅对一个函数名求值,在函数有参数时,必须加上参数表!!!
- 进阶用法 诡异的函数对齐问题 众所周知,C语言中存在这两种类型:struct和union,而在C++中区别于c语言存在更复杂的class类型,而对这三种数据类型操作时,代码如下:
struct sample
{
double a;
char b;
int c;
}
对于刚开始入门的兄弟来说,sizeof(sample)=sizeof(double)+sizeof(char)+sizeof(int)。。。然而并不是这样子的,编译器对一些变量的起始地址做了“对齐”处理。在默认情况下,编译器规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。在32位系统中,具体偏移方法如下:
Char //偏移量必须为sizeof(char)即1的倍数
int //偏移量必须为sizeof(int)即4的倍数
float //偏移量必须为sizeof(float)即4的倍数
double //偏移量必须为sizeof(double)即8的倍数
Short //偏移量必须为sizeof(short)即2的倍数
结构体中的变量在申请空间时,是按照顺序来申请空间,并且按照上面所示的对齐方式来调整位置,并且按照上述要求填充空字节。这样子说跟没说一样,所以说个例子吧:
- 当为上面的sample结构体分配空间时,肯定是先为double类型变量分配内存,他的起始地址和结构体的起始地址相同,偏移量0(正好为sizeof(double)的倍数),它占的内存为8字节这个就不用说了;然后为第二个char类型变量分配内存,可以为它分配的地址相对于结构的偏移地址为8,满足对齐方式可以分配,它占的内存为1个字节,完美!!!!;然后为第三个int类型变量分配内存,下一个可以分配的地址对于结构的偏移量为9,不是sizeof(int)的倍数,为了满足上述对偏移量balabala的诡异约束问题,编译器会填充三个空字节。。。使得下一个可分配地址对于结构原始地址偏移为12,满足要求,分配内存,完美!!!!!所以占用的空间大小为:8+1+3+4=16字节。(这个东西我记得在19年12月份我考浙江大学的计算机系时。。。408考试里考过,当时真的搞不懂,现在终于搞懂了,开心!!!!!!)