我是靠谱客的博主 伶俐哈密瓜,最近开发中收集的这篇文章主要介绍C语言sizeof的计算方式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

对于C语言开发人员来说,sizeof应该不陌生吧。此次我主要写的是sizeof对各变量长度的计算方式。
sizeof这个函数主要是对各数据类型的长度进行计算,入参为数据类型,返回值计算结果。但由于不同OS的系统架构下,sizeof计算的结果会存在一定的差异。下文主要基于32位系统,讨论sizeof的计算方式。
比较常见的场景是基本数据类型长度的计算结果如下:
类型
32位系统(bytes)
64位系统(bytes)
bool
1
1
char
1
1
short
2
2
int
4
4
long
4
8
long long
8
8
char *
4
8
float
4
4
double
8
8
long double
12
16

说明:char*代表指针变量,不管什么类型的指针,指针变量长度都是一样的。

为了加快CPU取数速度,C标准规定 变量存放地址一定为自身长度的整数倍。因此变量间就会出现缝隙空间,这时编译器在编译期间就会对这些缝隙进行填充,叫做变量的对齐与补齐规则。接下来我会举例说明各种场景下的对齐与补齐方式:
例1:
#include <stdio.h>
struct st
{
    char a;
    int b;
    short c;
    long d;
};
int main(void)
{
    struct st tmp;
    printf("&tmp.a=%pn",&(tmp.a));
    printf("&tmp.b=%pn",&(tmp.b));
    printf("&tmp.c=%pn",&(tmp.c));
    printf("&tmp.d=%pn",&(tmp.d));
    printf("sizeof(tmp)=%dn",sizeof(tmp));    
    return 0;
}
执行结果:
&tmp=0xbfe6e960
&tmp.a=0xbfe6e960
&tmp.b=0xbfe6e964
&tmp.c=0xbfe6e968
&tmp.d=0xbfe6e96c
sizeof(tmp)=16
从结果可以出成员变量的存放地址都是自身长度的整数倍。但结构体有所不同,结构体变量的地址应该为其最大成员变量长度的整数倍,且各成员变量遵守对齐与补齐规则,包括最后一个成员变量。所以 st结构体的大小为:1(a)+3(填充)+4(b)+2(c)+2(填充)+4(d)=16

例2:
struct st
{
    char a;
    int b;
    short c;
    long d;
    static int e;
};
结果:
sizeof(tmp)=16
在C++中可能会见到结构体中定义静态成员的代码,由于静态成员在定义时就已经分配的内存空间,所以用sizeof来计算结构体大小时,是不计算在内的。

例3:
struct st1
{
}tmp1;
结果:
sizeof(st1)=0
空结构体的大小为0,该类型不占用任何的地址空间。

例3:
void fun(void)
{
}
printf("sizeof(void)=%dn",sizeof(void));
printf("sizeof(fun)=%dn",sizeof(fun));
printf("sizeof(fun())=%dn",sizeof(fun()));
结果:
sizeof(void)=1
sizeof(fun)=1
sizeof(fun())=1
void类型的大小为1,sizeof也可以用来计算函数的大小以及返回值。
从执行文件的头部信息来看:
Num:    Value  Size Type    Bind   Vis      Ndx Name
48: 080483c4     5 FUNC    GLOBAL DEFAULT   13 fun
函数fun应该是占用5个字节的,这里不知道为什么打印出来只有1个字节?不过一般不会用sizeof来计算函数大小,没有什么意义。

例4:
struct st2
{
    char a:1;
    char b:4;
    char c:5;
    short d:10;
};
结果:
sizeof(st2)=4
这个例子结合位变量来说明字节对齐与补齐的规则,结构体中各成员变量存放如下:
|0|1234|567 01234567 01234567 01234567|   //4个字节长度
|a|   b   |       |   c    |      |        d          |                //4个变量存放
首先a占用了第一个字节的最低位,b占用了第1到第4位,由于c所占的位数超过了上一字节空闲的位数,所以c从下一字节的地址开始算起,占用第0到第4位。变量d由于是short型变量,需要以2字节对齐,所以地址从第3个字节的低位开始算,长度为10,余下6个位自动补齐。最终,该结构体大小为4字节。

例5:
union st2
{
    char a;
    shot b;
    int c;
};
结果:
sizeof(union)=4
联合体中成员是共享内存的,所以长度为最大成员变量的大小。

例6:
struct st
{
    char a;
    int b;
    short c;
    long d;          //最大长度为4
};
struct st2
{
    char a;
    short d;          //最大长度为2
    char e;
};
struct st4
{
    struct st a;             //16个字节
    struct st2 b;          //6个字节
};
结果:
sizeof(st4)=24
在st4结构体中,成员a占用16个字节,成员b占用6个字节,为什么 最终st4会占用24个字节呢?原因是a中变量最大长度为4,所以a以4字节对齐,b中变量最大长度为2,所以b以2字节对齐,但对于st4结构体来说,它内部基本数据类型最长为4字节,所以st4结构体以4字节对齐,最后会在后面填充2个字节。

总之,sizeof计算规则如下:
1、基本数据类型变量地址为自身长度的整数倍
2、对于结构体,sizeof会把编译器自动填充的字节算在内。
3、sizeof不计算静态变量的长度


C语言提供了#pragma宏可以指定字节对齐的长度:
例7:
#include <stdio.h>
#pragma pack(2)          //强制以2字节对齐
struct st
{
    char a;
    int b;
};
void main(void)
{
    printf("sizeof(struct st)=%dn",sizeof(struct st));
}
结果:
sizeof(struct st)=6
st结构体中成员b的初始地址不再是4的位数,而是2的倍数。

最后

以上就是伶俐哈密瓜为你收集整理的C语言sizeof的计算方式的全部内容,希望文章能够帮你解决C语言sizeof的计算方式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部