sizeof()的用法

1. 定义

sizeof 是一个操作符 operator,不是一个函数,
其作用是返回一个对象或类型所占的内存字节数
---------------------------------------------------------------------------------------------------------

2. 语法

sizeof object; //sizeof 对象
sizeof(object);
sizeof(type_name); // 例如 sizeof(int)

对象 object 可以是各种类型的变量,以及表达式(一般sizeof不会对表达式进行计算);sizeof对对象求内存大小,最终都是转化为对对象的数据类型进行求值;sizeof(表达式) 值为表达式的最终结果的数据类型的大小

int i;  
sizeof(int); //值为4  
sizeof(i); //值为4,等价于sizeof(int)  
sizeof i; //值为4  
sizeof(2); //值为4,等价于sizeof(int),因为2的类型为int  
sizeof(2 + 3.14); //值为8,等价于sizeof(double),因为此表达式的结果的类型为double  

char ary[sizeof(int) * 10]; //OK,编译无误

---------------------------------------------------------------------------------------------------------

3. 基本数据类型的 sizeof

基本数据类型如int short long char double等,其内存大小与系统有关。32位系统的int(4 Bytes), short(2 Bytes), long(4 Bytes), char(1 Bytes), double(8 Bytes), float(4 Bytes)

4. 结构体的 sizeof

结构体的 sizeof 涉及到字节对齐问题,字节对齐有助于加快计算机的存取速度,减小指令周期。为此,编译器会默认对结构体进行处理(实际上上其他地方的数据量也是如此),让宽度为 2 的基本数据类型(如short等)都位于能被 2 整除的地址上,让宽度为 4 的基本数据类型(如int等)都位于能被 4 整除的地址上,以此类推,这样,两个数中间就要加入填充字节,所以整个结构的sizeof值就比实际数据类型的内存值要大
字节对齐的细节和编译器的实现有关,但一般而言,满足3个准则:

  • 结构体变量的首地址能够被最宽基本类型成员的大小所整除
  • 结构体的每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要,编译器会在成员之间填充字节(internal adding)
  • 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员上加上填充字节(trailing padding)

注意:空结构体(不含数据成员)的 sizeof 值为 1 ,试想一个“不占空间“的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢,于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。

struct S1  
{  
    char a;  
    int b;  
};  
sizeof(S1); //值为 8,字节对齐,在char之后会填充 3 个字节。  
 
//-----------------------------------------------------------------------------------------
 
struct S2  
{  
    int b;  
    char a;  
};  
sizeof(S2); //值为 8,字节对齐,在char之后会填充 3 个字节。  
//-----------------------------------------------------------------------------------------

struct S3  
{  
};  
sizeof(S3); // 值为 1,空结构体也占内存
//-----------------------------------------------------------------------------------------

struct S4
{
    char a;
    int b;
    float c;
    double d;
};
sizeof(S4); //值为 24,在 a 后面补 3 个字节,在 c 和 d 之间补 4 个字节

struct S4_1
{
    double a;
    char b;
    int c;
    float d;
};
sizeof(S4_1);// 值为24, 在 b 后面补3个字节,为了使整体大小能够被最宽的double 8整除,需要在最后面加4个字节。

struct S4_2
{
    int a;
    double b;
    float c;
};
sizeof(S4_2);// 值为 24, 为了使double 的相对于首地址的偏移能够整除 8,在 a 后面补 4 个字节,为了使整体大小能够被最宽的double 8整除,需要在最后面加 4 个字节。

struct S4_3
{
    double d;
    int b;
    float c;
};
sizeof(S4_3); //值为 16,满足条件,不需要填补。
//-----------------------------------------------------------------------------------------

struct S5
{
    char a;
    S4_3 b;
    int c;
};
sizeof(S5); // 值为 32, 要满足结构体 S4_3的首地址可以被其最宽成员 double 8整除,在 a 后应该填充 7 个字节
           //然后为了满足总的成员大小能够被最宽成员 double 8 整除,在 int 后需要填充 4 个字节 

---------------------------------------------------------------------------------------------------------

5. 联合体的sizeof

结构体在内存组织上是顺序式的,联合体是重叠式的,各成员共享一段内存,所以整个联合体的sizeof就是每个成员sizeof的最大值

union u  
{  
    int a;  
    float b;  
    double c;  
    char d;  
};  
  
sizeof(u); // 值为 8

---------------------------------------------------------------------------------------------------------

6. 指针的sizeof

指针是用来记录另外一个对象的地址,所以指针的内存大小就是计算机内部地址总线的宽度
在32位计算机中,一个指针的sizeof返回值必定是4
指针变量的sizeof值与指针所指的对象没有任何关系

注意,数组名不等同于指针,其在sizeof下不一致

char *b = "helloworld";  
sizeof(b);  // 指针指向字符串, 值为 4
sizeof(*b); // 指针指向字符`h`,值为 1

//--------------------------------------------------------------------------------------

char a[10] = "hello";
sizeof(a); // 值为 10,数组名表示指向大小为10个字符的数组
sizeof(*a); // 值为 1,*a 指向数组的第一个字符

//---------------------------------------------------------------------------------------


char *c[10];  
sizeof(c); // 值为 40,c表示指向具有10个指针的指针数组,每个指针的大小为4,因此为40
sizeof(*c); // 值为 4,*c 指向指针数组的第一个元素

//-----------------------------------------------------------------------------------------


double *d;  
sizeof(d); // 值为 4, 指向 double 的指针
sizeof(*d); // 值为 8,*d 表示一个 double 的浮点数

 //-----------------------------------------------------------------------------------------

char **e;  
sizeof(e); // 值为 4,e 指向指针的指针
sizeof(*e); // 值为 4,*e 指向char字符的指针
sizeof(**e); // 值为 1,**e 表示 char 字符

//-----------------------------------------------------------------------------------------

char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)
void foo(char a[])
{
int b= sizeof( a ); // b == 4
}

void (*pf)();    
sizeof(pf); // 值为 4,指向函数的指针

---------------------------------------------------------------------------------------------------------

7. 数组的sizeof

数组名与指针不等同,数组名指向具有一定大小的数组,比指针多了数组长度

//--------------------------------------------------------------------------------------

char a[10] = "hello";
sizeof(a); // 值为 10,数组名表示指向大小为10个字符的数组
sizeof(*a); // 值为 1,*a 指向数组的第一个字符

//---------------------------------------------------------------------------------------

char *c[10];  
sizeof(c); // 值为 40,c表示指向具有10个指针的指针数组,每个指针的大小为4,因此为40
sizeof(*c); // 值为 4,*c 指向指针数组的第一个元素

//---------------------------------------------------------------------------------------

char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)
void foo(char a[])
{
int b= sizeof( a ); // b == 4,数组作为形参时,只传递地址指针,因此为 4,一般我们会再添加数组长度作为形参
}

---------------------------------------------------------------------------------------------------------

8. 函数的 sizeof

  • sizeof 对函数函数求值,其结果是函数返回值类型的大小,函数并不会被调用
  • 注意:
    • 不能对函数返回值为空的函数求值
    • 不能对函数名求值
    • 对有参数的函数,在用 sizeof时,必须写上实参表
#include <iostream>  
using namespace std;  
  
float FuncP(int a, float b)  
{  
    return a + b;  
}  
  
int FuncNP()  
{  
    return 3;  
}  
  
void Func()  
{  
}  
  
int main()  
{  
cout<<sizeof(FuncP(3, 0.4))<<endl; //OK,值为4,sizeof(FuncP(3,0.4))相当于sizeof(float)  
cout<<sizeof(FuncNP())<<endl; //OK,值为4,sizeof(FuncNP())相当于sizeof(int)  
/*cout<<sizeof(Func())<<endl; //error,sizeof不能对返回值为空类型的函数求值*/  
/*cout<<sizeof(FuncNP)<<endl; //error,sizeof不能对函数名求值*/  
return 0;  
}

void (*pf)();    
sizeof(pf); // 值为 4,指向函数的指针
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 首先感觉本文原作者的分享 w57w57w57的专栏-CSDN博客网址: http://blog.csdn.net/...
    HelloGeekBand阅读 2,351评论 0 7
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,498评论 1 51
  • “电影要开始了,加油!你一定可以的!”他对着镜子里的自己说到。 这是他们在一起的第五百二十一天,他中午要向深爱的她...
    玖柒柒i阅读 366评论 1 0
  • 我是一个非常讨厌麻烦的人,有很决绝,所以,离我远点吧
    天上一只叔阅读 65评论 0 0
  • 雨打湿了写满诗的叶薄情的伞,将哀怨揉成泥土不顾裤脚抖瑟的墨迹与呜咽风只管高声吟唱,偷藏的只言片语 断弦的琴,最后一...
    夏爅阅读 266评论 4 3