博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c语言 sizeof详解
阅读量:4145 次
发布时间:2019-05-25

本文共 4357 字,大约阅读时间需要 14 分钟。

sizeof的概念  

  sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。
    它并不是函数。
    sizeof操作符以字节形式给出了其操作数的存储大小。
    操作数可以是一个表达式或括在括号内的类型名。
    操作数的存储大小由操作数的类型决定。 

sizeof的使用方法  

  1、用于数据类型    
  sizeof使用形式: sizeof(type)
  数据类型必须用括号括住: sizeof(int)
  2、用于变量    
  sizeof使用形式: sizeof(var_name) 或 sizeof var_name    
  变量名可以不用括号括住.如sizeof (var_name),sizeof var_name等都是正确形式
    带括号的用法更普遍,大多数程序员采用这种形式。    
  注意:sizeof操作符不能用于函数类型,不完全类型或位字段。
     不完全类型指具有未知存储大小的数据类型,
     如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。    
    例如: sizeof(max)     
--
若此时变量max定义为int max();
      sizeof(char_v) 
   --若此时char_v定义为char char_v[MAX]且MAX未知,
      sizeof(void)      
     以上都是不正确形式。

sizeof的结果

  1、ANSI C正式规定字符类型为1字节。    
    sizeof(char)= 1;
    sizeof(unsigned char) = 1;
    sizeof(signed char)= 1;
  
  2、其他类型在ANSI C中没有具体规定,大小依赖于实现。
    sizeof(int)= 4;
    sizeof(unsigned int)= 4;
    sizeof(short int)= 2;
    sizeof(unsigned short) = 2;
    sizeof(long int)= 4;
    sizeof(unsigned long)= 4;
    sizeof(float)= 4;
    sizeof(double)= 8;
    sizeof(long double)= 12; //gcc 32-bit 编译器
    sizeof(long double)= 16; //gcc 64-bit 编译器
  3、当操作数是指针时,sizeof依赖于编译器。
    学过数据结构的你应该知道指针是一个很重要的概念,它记录了另一个对象的地址。既然是来存放地址的,那么它当然等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的返回值必定是4(注意结果是以字节为单位),在64位系统中指针变量的sizeof结果为8。
       例如: char *p;      
           sizeof(p) = 4;//gcc 32-bit 编译器
           sizeof(p) = 8;//gcc 64-bit 编译器     
 
  4、当操作数具有数组类型时,其结果是数组的总字节数。
    例如: char a[5];
        int  b[5];
        sizeof(a) = 5;
        sizeof(b) = 20;
   
  5、当操作数是具体的字符串或者数值时,会根据具体的类型进行相应转化。
      例如: sizeof(8)    = 4;  //自动转化为int类型
          sizeof(8.8)  = 8;  //自动转化为double类型,注意,不是float类型
          sizeof("ab") = 3   //自动转化为数组类型,
                                   
  6、当操作数是联合类型时,sizeof是其最大字节成员的字节数。当操作数是结构类型时,sizeof是其成员类型的总字节数,包括补充字节在内。还是拿例子来说话:
   union u{             //对union来说
       char c;
       double d;
     }u;
    sizeof(u) = max(sizeof(c),sizeof(d)) = sizeof(1,8) = 8;
  struct a{             //对struct来说
       char b; 
       double x;
    }a;   
   sizeof(a) = 16;  而一般sizeof(char) + sizeof(double) = 9; 
  这是因为编译器在
时,在结构中插入空位以控制各成员对象的地址对齐。但如果全对齐的话,sizeof(a) = 16, 这是因为b被放到偏移量为0的地址,占1个字节;在存放x时,double类型长度为8,需要放到能被8整除的偏移量上,这时候需要补7个空字节, 达到8个,这时候偏移量为8,放上x后长度为16。
struct S1 {		char c;		double d;	};	union  u {            //对union来说		char c;		double d;	} u;	int a;	char b;	short c;	double d;	float f;	int *p;	char a1[]="abcd";	int a2[3];	printf("int=%d\n",sizeof(a));	printf("char=%d\n",sizeof(b));	printf("short=%d\n",sizeof(c));	printf("double=%d\n",sizeof(d));	printf("float=%d\n",sizeof(f));	printf("指针=%d\n",sizeof(p));	printf("数组=%d\n",sizeof(a1));	printf("数组=%d\n",sizeof("ab"));	printf("结构体=%d\n",sizeof(S1));	printf("联合类型=%d\n",sizeof(u));
gcc 64-bit 编译器,指针=8;
gcc 32-bit 编译器,指针=4

类的sizeof

面试中遇到面试官让我求一个类的sizeof,里边有各种类型的变量,还有虚函数(但是不懂什么是虚函数)。如果有虚函数就要加上一个指向虚表的指针,4字节大小(32 位 编译器),64位编译器是8字节大小。
1、空类
class A{}; sizeof(A)=1;
求sizeof的结果是1,因为即使是没有成员之类的,一个类存在,至少都要给他一个空间,不然就没有存在的意义了。
2、简单的类
class A{	int a;    	double b;};
本来sizeof(A.a)+sizeof(A.b)=12;结果=16,说明类的大小也遵守类似struct字节对齐的补齐规则,补齐为double类型8字节,所有为16
3、含虚函数的类
class A{	int a;	virtual  fun();};
//sizeof(A)=8+8=16   (gcc-64bit编译器,指针大小为8字节)+补齐规则
//sizeof(A)=4+4=8   (gcc-32bit编译器,指针大小为4字节)
3、子类继承父类,含虚函数
class Base{public:	Base();                	virtual ~Base();         //每个实例都有虚函数表	void set_num(int num)    //普通成员函数,为各实例公有,不归入sizeof统计	{		a=num;	}private:    int  a;                  //占4字节    char *p;                 //4字节指针};class Derive:public Base{public:	Derive():Base(){};     	~Derive(){};private:	static int st;         //非实例独占   	int  d;                     //占4字节   	char *p;                    //4字节指针};
gcc-32bit编译器
sizeof(Base)=12;
sizeof(Derive)=20
sizeof(Derive)=sizeof(Base)+sizeof(Derive.d)+sizeof(Derive.p) 的指针即可;
gcc-64bit编译器
sizeof(Base)=24; //补齐规则
sizeof(Derive)=40
sizeof(Derive)=sizeof(Base)+sizeof(Derive.d)+sizeof(Derive.p)
因为普通继承,子类和父类的虚函数存放在同一个虚表中,所以,只需要存一个指向虚表
4.子类虚继承、父类含虚函数
class Base{public:	Base();                	virtual ~Base();         //每个实例都有虚函数表	void set_num(int num)    //普通成员函数,为各实例公有,不归入sizeof统计	{		a=num;	}private:    int  a;                  //占4字节    char *p;                 //4字节指针};class Derive:virtual public Base{public:	Derive():Base(){};     	~Derive(){};private:	static int st;         //非实例独占   	int  d;                     //占4字节   	char *p;                    //4字节指针};
sizeof(Derive)=sizeof(Base)+虚函数指针(指示父类存放空间的起始偏移量)+sizeof(Derive.d)+sizeof(Derive.p)
虚继承时,父类和子类的虚函数表分开放,所以,分别存储两个指向对应续表的指针,因而不用减去sizeof(A)中续表指针的大小。
类的sizeof总结:
1.类的大小为类的非静态成员数据类型大小之和,也就是说静态成员数据不作考虑
2.普通成员函数与sizeof无关
3.虚函数由于要维护在虚函数表,所以要占据一个指针大小字节
4.类的总大小也遵守类似struct字节对齐的,调整规则。
参考:http://blog.csdn.net/hairetz/article/details/4171769
http://blog.sina.com.cn/s/blog_728161840100u2ib.html
你可能感兴趣的文章
Angular.JS + Require.JS + angular-async-loader 来实现异步加载 angular 模块
查看>>
怎么设置可以把dropdown设成可以输入数据
查看>>
Javascript Versions
查看>>
用javascript动态调整iframe高度
查看>>
subclipx v1.02 - 简单实用的轻量级多维剪贴板工具
查看>>
让Java程序自带JRE
查看>>
最近写了一个简单的面向对象的脚本语言 Q 语言
查看>>
可完全定制的Javascript日历 (Callback 实现)
查看>>
一切都是对象
查看>>
Q 语言 -- 字符串
查看>>
Q 语言 -- 数组
查看>>
Q 语言 -- HashMap
查看>>
document.getElementByClass
查看>>
JAVA 进程异常高的 CPU 占用率
查看>>
Delphi 使用 RTTI 动态通过名称调用函数和设置控件属性值
查看>>
用 Java 把 html 转成 pdf
查看>>
得到 Linux, Unix 终端大小
查看>>
Humpic JDBC Logger 监控SQL语句。
查看>>
subclipx v1.07 - 简单实用的轻量级多维剪贴板工具
查看>>
[刷机教程] [Root] S-OFF的同学来Root你的HTC Desire S
查看>>