关于sizeof(struct) 问题,字节对齐,有详细说明最好wen
#pragma pack(3)
struct astruct{
char w;
int a;
char r;
int c;
double b;
}; //sizeof(astruct)=13
问题点数:20、回复次数:10Top
1 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-06-01 20:12:17 得分 0
看来又要拿分了:)
关键字:sizeof,字节对齐,多继承,虚拟继承,成员函数指针
前向声明:
sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下。
但当我总结的时候才发现,这个问题既可以简单,又可以复杂,所以本文有的地方并不适合初学者,甚至都没有必要大作文章。但如果你想“知其然,更知其所以然”的话,那么这篇文章对你或许有所帮助。
菜鸟我对C++的掌握尚未深入,其中不乏错误,欢迎各位指正啊
1. 定义:
sizeof是何方神圣sizeof乃C/C++中的一个操作符(operator)是也,简单的说其作用就是返回一个对象或者类型所占的内存字节数。
MSDN上的解释为:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.
其返回值类型为size_t,在头文件stddef.h中定义。这是一个依赖于编译系统的值,一般定义为
typedef unsigned int size_t;
世上编译器林林总总,但作为一个规范,它们都会保证char、signed char和unsigned
char的sizeof值为1,毕竟char是我们编程能用的最小数据类型。
2. 语法:
sizeof有三种语法形式,如下:
1) sizeof( object ); // sizeof( 对象 );
2) sizeof( type_name ); // sizeof( 类型 );
3) sizeof object; // sizeof 对象;
所以,
int i;
sizeof( i ); // ok
sizeof i; // ok
sizeof( int ); // ok
sizeof int; // error
既然写法3可以用写法1代替,为求形式统一以及减少我们大脑的负担,第3种写法,忘掉它吧!实际上,sizeof计算对象的大小也是转换成对对象类型的计算,也就是说,同种类型的不同对象其sizeof值都是一致的。这里,对象可以进一步延伸至表达式,即sizeof可以对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,一般不会对表达式进行计算。如:
sizeof( 2 ); // 2的类型为int,所以等价于 sizeof( int );
sizeof( 2 + 3.14 ); // 3.14的类型为double,2也会被提升成double类型,所以等价于 sizeof( double );
sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用,我们来看一个完整的例子:
char foo()
{
printf("foo() has been called.\n");
return 'a';
}
int main()
{
size_t sz = sizeof( foo() ); // foo() 的返回值类型为char,所以sz = sizeof(char ),foo()并不会被调用
printf("sizeof( foo() ) = %d\n", sz);
}
C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的:
sizeof( foo );// error
void foo2() { }
sizeof( foo2() );// error
struct S
{
unsigned int f1 : 1;
unsigned int f2 : 5;
unsigned int f3 : 12;
};
sizeof( S.f1 );// error
3. sizeof的常量性
sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,如:
char ary[ sizeof( int ) * 10 ]; // ok
最新的C99标准规定sizeof也可以在运行时刻进行计算,如下面的程序在Dev-C++中可以正确执行
Top
2 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-06-01 20:13:30 得分 0
贴这么多吧
实在太长了
你上我blog上看吧足有几万字:)
http://blog.csdn.net/wanfustudio/
Top
3 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-06-01 20:14:07 得分 0
http://blog.csdn.net/wanfustudio/archive/2006/05/02/705681.aspxTop
4 楼happytang(一只叫苏格拉底的猪)回复于 2006-06-01 21:02:41 得分 0
2.1 自然对界
struct是一种复合数据类型,其构成元素既可以是基本数据类型(如 int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。
例如:
struct naturalalign
{
char a;
short b;
char c;
};
在上述结构体中,size最大的是short,其长度为2字节,因而结构体中的char成员a、c都以2为单位对齐,sizeof(naturalalign)的结果等于6;
如果改为:
struct naturalalign
{
char a;
int b;
char c;
};
其结果显然为12。
指定对界
一般地,可以通过下面的方法来改变缺省的对界条件:
· 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。
例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
当n为4、8、16时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n为2时,其发挥了作用,使得sizeof(naturalalign)的结果为8。
Top
5 楼happytang(一只叫苏格拉底的猪)回复于 2006-06-01 21:47:31 得分 0
http://www.blogcn.com/user43/gjloveht/index.html
http://vcpro.blogchina.com/1253903.html
1、2、4、8、16为#pragma pack(n)中n的字节数,其他不符合的都按默认为8
你这个题不对吧,这样编译通过,sizeof也是24
n为2/4,sizeof就是20Top
6 楼jixingzhong(瞌睡虫·星辰)回复于 2006-06-01 22:01:42 得分 0
楼主用的是 TC 吧,
得到的结果是 14 唉,
怎么会是 13 呢 ...
一般#pragma pack 跟的参数都是 2的次方,
没有用 3 这么怪异的 ...Top
7 楼jixingzhong(瞌睡虫·星辰)回复于 2006-06-01 22:10:45 得分 0
#pragma pack(3)
struct astruct{
char w; //内存编址 0 ,这里是一个相对编址
int a; //TC中为2字节,对齐到2,内存为2,3
char r; //内存编址 4
int c; //对齐, 内存编址 6,7
double b; //对齐,注意pragma pack(3),对齐到3,内存编址 9,10,11,12
};
使用的内存是 0-12 共13字节,
楼主的答案不是这么得到的吧 ?
呵呵,注意最后所有空间还需要对齐操作的 ......Top
8 楼jixingzhong(瞌睡虫·星辰)回复于 2006-06-01 22:17:45 得分 0
好像高错了,
double 是8字节的....
似乎所有的变量对齐到 1 就有14个字节的空间了吧 ....Top
9 楼jixingzhong(瞌睡虫·星辰)回复于 2006-06-01 22:21:15 得分 0
16位TC下:
#pragma pack(3)
struct astruct{
char w; //内存编址 0 ,这里是一个相对编址
int a; //TC中为2字节,对齐到2,内存为2,3
char r; //内存编址 4
int c; //对齐, 内存编址 6,7
double b; //对齐,注意pragma pack(3),对齐到3,
//内存编址 9,10,11,12,13,14,15,16
};
使用 0-16 共17字节,
对齐到 min[3, sizeof(double)] = 3,
结果应该是 18 字节 ...Top
10 楼jixingzhong(瞌睡虫·星辰)回复于 2006-06-01 22:23:22 得分 0
32位环境下, 比如VC:
#pragma pack(3)
struct astruct{
char w; //内存编址 0 ,这里是一个相对编址
int a; //4字节,对齐到3,内存为3,4,5,6
char r; //内存编址 7
int c; //对齐, 内存编址 9,10,11,12
double b; //对齐,注意pragma pack(3),对齐到3,
//内存编址 15,16,17,18,19,20,21,22
};
使用 0-22 共23字节,
对齐到 min[3, sizeof(double)] = 3,
结果应该是 24 字节 ...Top




