在C/C++中,用sizeof来获取数据类型以及变量等占用的字节数。例如使用VC编译器,sizeof(char)=1 。但这个编译系统有关系,例如在VC下sizeof(int) = 4,在VxWorks下sizeof(int) =2。
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
- 对于基本类型的变量,大小就是变量类型的大小;数组就是数组的长度*每个元素的大小。
请看下面的测试代码和相应的输出:
INT TestSizeOf()
{
char chA = 'C';
int inB = 0;
char chArray[100];
cout << "sizeof(char)=" << sizeof(char) << endl;
cout << "sizeof(chA)=" << sizeof(chA) << endl;
cout << "sizeof(int)=" << sizeof(int) << endl;
cout << "sizeof(inB)=" << sizeof(inB) << endl;
cout << "sizeof(chArray)=" << sizeof(chArray) << endl;
return LRet_Success;
}
输出:
sizeof(char)=1
sizeof(chA)=1
sizeof(int)=4
sizeof(inB)=4
sizeof(chArray)=100
2. 对于结构(struct)和类(class),不仅要考虑成员变量的大小相关,还要考虑对齐(例如32位操作系统最小分配单元是4),在某些编译器还要考虑成员变量的顺序有关
下面两个结构:
struct Tstruct1
{
char a;
char b;
char c;
int e;
double f;
};
struct Tstruct2
{
char a;
int e;
char b;
double f;
char c;
};
测试代码:
cout << "sizeof(Tstruct1)=" << sizeof(Tstruct1) << endl;
cout << "sizeof(Tstruct1)=" << sizeof(Tstruct1) << endl;
使用visual stdio 2008,输出结果:
sizeof(Tstruct1)=16
sizeof(Tstruct2)=32
对上面的结果解释一下:
第一个结构Tstruct1中,a,b,c各占一个字节,假设占用的分别是存储空间0,1,2。接下来的变量是int(需要4个字节),由于接下来可用的地址空间是3,不是4的倍数,因此存储空间被放上填充字节,e放在4开始的空间。再接下来是一个double类型,需要8个字节,因此总共需要16个字节。
第二个结构Tstruct2中,假设a占用地址空间0,接下来的e的起始位置是4,接下来b占用的起始位置是8,b占用一个字节,接下来可用的空间是9,由于接下来的是一个double类型(需要8个字节),因此f占用的起始位置是16。最后一个成员变量是一个char类型,需要一个存储空间,整个结构中最宽的基本类型是double(需要8个存储空间),因此为了整个结构占用的存储空间是8的整数倍,在最后填充7个字节,因此整个结构Tstruct2的存储大小是32。
我们再看一个空的结构:
struct Tstruct3
{
};
即使没有成员,也需要至少占用一个空间。试想如果没有分配存储空间,那么定义一个Tstruct3型变量t3,那么取t3的地址怎么办?
3.指针和数组作为函数参数
在32位系统下,指向任何类型的指针都占用4个字节,数组占用的空间大小 = 每个元素的大小*数组长度。、
那么将数组作为函数参数,那么该参数占用的空间是多少呢?
请看下面的测试代码:
int TestArrayPara(int a[100][100])
{
cout << "sizeof(a) =" << sizeof(a);
return LRet_Success;
}
void main()
{
int a[100][100];
TestArrayPara(a);
}
运行的结果:
sizeof(a) =4
这个很容易解释,数组作为参数传给函数,传递的是数组的首址,而不是数组本身。