sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。
C语言中,对 sizeof() 的处理都是在编译阶段进行,所以它可以被当作常量表达式使用。其作用就是返回一个对象或者类型所占的内存字节数。
这里的类型是指数据类型,比如int、long、数组、指针、结构体等。
这里的对象可以是变量、数据类型、函数调用。
内存字节数来源于储存器中的概念。存储器的容量是以字节为基本单位的。也就是说一个内存地址代表一个字节的存储空间。
sizeof计算对象的大小也是转换成对对象类型的计算,也就是说,同种类型的不同对象其sizeof值都是一致的。sizeof对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,一般不会对表达式进行计算。
特别的,sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用;函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值。
具体用法如下:
sizeof(type_name);//sizeof(类型);
sizeof object;//sizeof对象;
举例说明:
int i;
sizeof(i);//ok
sizeof i;//ok
sizeof(int);//ok
sizeof int;//error
下面依次举例介绍部分数据类型和对象的具体应用。
这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型,由于它们都是和系统相关的,所以在不同的系统下取值可能不同。
一般的,在32位编译环境中,sizeof(int)的取值为4。
指针变量,是指可以用来存放另一个对象的地址的变量。指针变量里面存放的是指针,即地址。在不同的系统中,地址的表示位数不同。如在32位系统中,地址是32位表示的。
当一个字节8位时,在32为系统中,说一个储存器的地址范围一般是说 0x 00 00 00 00 ~ 0x 00 00 4F 00;而在16位系统中,地址是该范围是说0x 00 00~ 0x 4F 00。
综上,在32位计算机中,一个指针变量的sizeof返回值通常是4,在64位系统中指针变量的sizeof的返回值通常为8。
指针变量的在C语言中的定义是为了为指向的对象预分配内存地址。指针变量的sizeof值与指针所指的对象没有任何关系,所以同一系统中所有的指针变量所占内存大小相等。
数组的sizeof值等于数组所占用的内存字节数。
注意:字符串数组,最后一个还有终止符。
结构体在内存中是按照一定的原则进行存储的。
原则1:数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
原则2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
原则3:收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
因此
1 结构体sizeof的结果不是简单的加所有成员的字节数相加;
2 结构体sizeof的结果和不同数据类型在结构体中的位置有关;比如:
struct A{
int a;
char b;
short c;
};
struct B{
char b;
int a;
short c;
};
在32位操作系统中,sizeof(A)的结果是8;sizeof(A)的结果是12。
这是因为在内存中的存储如下:
a b c
A的内存布局:1111, 1*, 11
b a c
B的内存布局:1***, 1111, 11**
其中,*表示补充。
sizeof返回的是内存字节数。内存字节数来源于储存器中的概念。存储器的容量是以字节为基本单位的。也就是说一个内存地址代表一个字节的存储空间。
对于其他一般的处理器,一个内存地址是8位。但在DSP中,一个内存地址不一定是8位。以TI的C2000为例,一个内存地址是16位。
图中,一个内存地址对应16位,以L0 SARAM为例,地址0x00 8000~0x00 8800,内存地址长度为0x800 = 2K,而一个内存地址16位,所以L0 SARAM的存储大小为2K x 16。
在TI的C2000中,使用sizeof得到结构体的内存字节数,当结构体中只定义一个Uint16的变量时,sizeof的返回值为1;结构体中有一个int32 和int16时,返回值为4。
如下:
struct {
Uint32 Ver0;
Uint16 Ver1;
} infoVersion_P;
sizeof(infoVersion_P)的结果是4。
struct {
Uint16 Ver1;
} infoVersion_P1;
sizeof(infoVersion_P1)的结果是1。
DSP使用的是28033,该芯片一个地址对应16位。因此结构体只有Uint16一个成员的时候,sizeof的返回值是1。
结构体在存储的时候,内存对齐。因此,结构体中有一个int32 和int16时,占用的是4个地址。所以sizeof的返回值是4。
要使用sizeof来返回结构体的内存字节数时,定义的结构体最好按照32位,便于后期和其他人维护。
在查询资料时发现,C2000中除了一个地址对应16位是非常规的,还有关于char也是非常规的。char是16位的定义。
还是以28033为例,其使用的CPU如数据手册所示:
使用编译器甄别,分别给一个char变量赋值16位和32为数值,赋值16为数值,编译器正常无问题;赋值32为,编译器报错。所以,char确实是16位的。