2008年(18)
分类: C/C++
2008-04-08 11:07:12
(
2、语法格式 sizeof有三种语法形式,如下:
2) 用于变量 sizeof( object ); // sizeof( 对象 );
sizeof object; // sizeof 对象;
所以,
int i;
sizeof( i ); // ok
sizeof i; // ok
sizeof( int ); // ok
sizeof int; // error
注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。
3、sizeof操作符的结果
sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
ANSI C正式规定字符类型为
2)int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、 float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、 4、4、4、8、
3)当操作数是指针时,sizeof依赖于编译器。例如Microsoft C/C++7.0中,near类指针字节数为2,far、huge类指针字节数为4。一般Unix的指针字节数为4。
4)当操作数具有数组类型时,其结果是数组的总字节数。
5)联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补在内。
让我们看如下结构:
struct {char b; double x;} a;
在某些机器上sizeof(a)=
这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。如double类型的结构成员x要放在被4整除的地址。
6)如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
4、sizeof与其他操作符的关系
sizeof的优先级为2级,比/、%等3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeof(int);其中i为int类型变量。
5、sizeof的主要用途
void *malloc(size_t size),
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。
2)sizeof的另一个的主要用途是计算数组中元素的个数。例如:
void * memset(void * s,int c,sizeof(s))。
6、建议
由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。
(2)sizeof用法
假设以后的程序都是32位C的程序。
int i=
在这里由于是32位的C 程序,故对于一个整型变量应该用32位来存放,
sizeof(i)为4字节;
sizeof(int)也为4字节;
char a='b';
char b[]="hello,world";
char c[20]="hello,world";
char *p=b;
明显sizeof(a)为
b为数组名sizeof是求取数组所占内存的大小,故sizeof(b)为
因为 p指针变量是一个地址,地址信息又用32位来存放,所以sizeof(p)为4;
sizeof(*p)为数组b的大小。;
由于在定义数组时指定了数组的大小sizeof(c)故为20,在这里hello,world仅为
我们对sizeof有初步的了解了,再接下来看这样的一个结构
struct
int a;
char b;
int c;
} ;
问sizeof(s
如果是用那样来进行存储的的话,那么在读取这些变量时PC指针一会加4,而一会加
在这里主要看一下char在这里占的空间。这里是32为的程序,故int占4个字节,没有调整内存对齐的方式,故应该按照默认的方式进行内存对齐。在此结构里面应按照4个字节对齐效率最好。故char在这里占的空间也应该为4个字节。后面有3填充字节。
在分析下面的结构
struct s2{
int a;
char b;
int c;
s
} ;
sizeof(s2)等于多少? 为24字节。
#include
void print(char a[])
{ printf("%d\n",sizeof(a));
}
main()
{ char a[]="hello,world";
print(a);
}
运行的结果是什么呢? 或许你会认为结果是
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trai
对于上面的准则,有几点需要说明:
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要获得S2中c的偏移量,方法为
size_t pos = offsetof(S2, c);// pos等于4
2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
含位域结构体的sizeof
前面已经说过,位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在。使用位域的主要目的是压缩存储,其大致规则为:
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
还是让我们来看看例子。
示例:
struct BF
{
char f
char f2 : 4;
char f3 : 5;
};
其内存布局为:
|_f
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
0 3 7 8
位域类型为char,第
能从下一个字节开始。因此sizeof(BF
示例:
struct BF2
{
char f
short f2 : 4;
char f3 : 5;
};
由于相邻位域类型不同,在VC6中其sizeof为6,在Dev-C++中为2。
示例:
struct BF3
{
char f
char f2;
char f3 : 5;
};
非位域字段穿插在其中,不会产生压缩,在VC6和Dev-C++中得到的大小均为3。
联合体的sizeof
结构体在内存组织上是顺序式的,联合体则是重叠式,各成员共享一段内存,所以整个联合体的sizeof也就是每个成员sizeof的最大值。结构体的成员也可以是复合类型,这里,复合类型成员是被作为整体考虑的。
所以,下面例子中,U的sizeof值等于sizeof(s)。
union U
{
int i;
char c;
S
};
---------补充----------------------------
参数为结构或类。Sizeof应用在类和结构的处理情况是相同的。但有三点需要注意:
第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。
第二、没有成员变量的结构或类的大小为
第三、类中含有虚函数的情况,虚函数表指针占用4个字节大小,并且放在类的开头。即虚函数在类中的位置对类的大小无影响,其始终是在最前面的。
下面举例说明,
2、Test *s;//sizeof(s)=4,s为一个指针。
3、Class test
4、class A
{
double a;
char b;
virtual p(){};
};//sizeof(A)=24,因为类中有虚函数,所以等价于下面:
class A
{
[color=#FF0000]void [/color]*p; //虚函数表指针
double a;
char b;
};