首页 > 其他分享 >笔记整理--C语言--sizeof()用法汇总——转载

笔记整理--C语言--sizeof()用法汇总——转载

时间:2023-08-17 09:57:55浏览次数:38  
标签:对界 -- double C语言 char int sizeof struct

sizeof()功能:计算数据空间的字节数

与strlen()比较

  1. strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素。
  2. 而sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示。

指针与静态数组的sizeof操作

指针均可看为变量类型的一种。所有指针变量的sizeof 操作结果均为4。

注意:

int *p; sizeof(p) = 4;
但sizeof(*p)相当于sizeof(int);

对于静态数组,sizeof可直接计算数组大小;

int a[10]; char b[] = "hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;

注意:

数组做型参时,数组名称当作指针使用!!

void  fun(char p[])
{
    sizeof(p) = 4
}

经典问题:

double* (*a)[3][6];
cout<<sizeof(a)<<endl; // 4 a为指针
cout<<sizeof(*a)<<endl; // 72 *a为一个有3*6个指针元素的数组
cout<<sizeof(**a)<<endl; // 24 **a为数组一维的6个指针
cout<<sizeof(***a)<<endl; // 4 ***a为一维的第一个指针
cout<<sizeof(****a)<<endl; // 8 ****a为一个double变量

问题解析:

a是一个很奇怪的定义,他表示一个指向double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。

既然a是执行double[3][6]类型的指针,a就表示一个double[3][6]的多维数组类型,因此sizeof(a) = 3 * 6 * sizeof(double*) = 72。

同样的,**a表示一个double[6]类型的数组,所以sizeof(**a)=6 * sizeof (double) = 24。
***a就表示其中的一个元素,也就是double*了,所以sizeof(***a) = 4。

至于****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。

格式的写法

sizeof操作符,对变量或对象可以不加括号,但若是类型,须加括号。

使用sizeof时string的注意事项

string s="hello";
sizeof(s)等于string类的大小,sizeof(s.c_str())得到的是与字符串长度。

union 与struct的空间计算

总体上遵循两个原则:

  1. 整体空间是 占用空间最大的成员(的类型)所占字节数的整倍数
  2. 数据对齐原则----内存按结构成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整倍数,如果不够则补齐,以此向后类推... ...

注意:

数组按照单个变量一个一个的摆放,而不是看成整体。如果成员中有自定义的类、结构体,也要注意数组问题。

例:[引用其他帖子的内容]
因为对齐问题使结构体的sizeof变得比较复杂,看下面的例子:(默认对齐方式下)

struct s1
{
    char a;
    double b;
    int c;
    char d;
};

struct s2
{
    char a;
    char b;
    int c;
    double d;
};

cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 16

同样是两个char类型,一个int类型,一个double类型,但是因为对齐问题,导致他们的大小不同。计算结构体大小可以采用元素摆放法,

我举例子说明一下:首先,CPU判断结构体的对界,根据上一节的结论,s1和s2的对界都取最大的元素类型,也就是double类型的对界8。然后开始摆放每个元素。

对于s1,首先把a放到8的对界,假定是0,此时下一个空闲的地址是1,但是下一个元素d是double类型,要放到8的对界上,离1最接近的地址是8了,所以d被放在了8,此时下一个空闲地址变成了16,下一个元素c的对界是4,16可以满足,所以c放在了16,此时下一个空闲地址变成了20,下一个元素d需要对界1,也正好落在对界上,所以d放在了20,结构体在地址21处结束。由于s1的大小需要是8的倍数,所以21-23的空间被保留,s1的大小变成了24。

对于s2,首先把a放到8的对界,假定是0,此时下一个空闲地址是1,下一个元素的对界也是1,所以b摆放在1,下一个空闲地址变成了2;下一个元素c的对界是4,所以取离2最近的地址4摆放c,下一个空闲地址变成了8,下一个元素d的对界是8,所以d摆放在8,所有元素摆放完毕,结构体在15处结束,占用总空间为16,正好是8的倍数。

这里有个陷阱,对于结构体中的结构体成员,不要认为它的对齐方式就是他的大小,看下面的例子:

struct s1
{
    char a[8];
};

struct s2
{
    double d;
};

struct s3
{
    s1 s;
    char a;
};

struct s4
{
    s2 s;
    char a;
};
cout<<sizeof(s1)<<endl; // 8
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl; // 9
cout<<sizeof(s4)<<endl; // 16;

s1和s2大小虽然都是8,但是s1的对齐方式是1,s2是8(double),所以在s3和s4中才有这样的差异。
所以,在自己定义结构体的时候,如果空间紧张的话,最好考虑对齐因素来排列结构体里的元素。

补充:不要让double干扰你的位域

在结构体和类中,可以使用位域来规定某个成员所能占用的空间,所以使用位域能在一定程度上节省结构体占用的空间。不过考虑下面的代码:

struct s1
{
    int i: 8;
   int j: 4;
   double b;
   int a:3;
};

struct s2
{
   int i;
   int j;
   double b;
   int a;
};

struct s3
{
   int i;
   int j;
    int a;
    double b;
};

struct s4
{
    int i: 8;
    int j: 4;
    int a:3;
    double b;
};

cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 24
cout<<sizeof(s3)<<endl; // 24
cout<<sizeof(s4)<<endl; // 16

可以看到,有double存在会干涉到位域(sizeof的算法参考上一节),所以使用位域的的时候,最好把float类型和double类型放在程序的开始或者最后。

相关常数:

sizeof int:4
sizeof short:2
sizeof long:4
sizeof float:4
sizeof double:8
sizeof char:1
sizeof p:4
sizeof WORD:2
sizeof DWORD:4

标签:对界,--,double,C语言,char,int,sizeof,struct
From: https://www.cnblogs.com/stlong/p/17636742.html

相关文章

  • [Microsoft Azure] 快速上手创建Azure App Service服务
    本文将带您快速了解如何使用MicrosoftAzure创建AzureAppService服务,让您在短时间内掌握这一流行的云计算平台。 MicrosoftAzure是一个功能强大的云计算平台,提供了广泛的云服务,包括虚拟机、数据库、存储等。在本篇博客中,我们将重点介绍AzureAppService服务的创建过程。A......
  • 代码随想录算法训练营第十七天| 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子
     卡哥建议:迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。  110.平衡二叉树 (优先掌握递归)   卡哥建议:再一次涉及到,什么是高度,什么是深度,可以巩固一下。   题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%......
  • MyBatis居然也有并发问题
    日志上了服务器一看,Mybatis报错,接口还是个相当频繁的接口,一想,完了,绩效大概率不保。 log2023-08-0809:52:05,386|aaaaaaaaa|XXXXXXXXXXXXXX|unknownexceptionoccurredorg.mybatis.spring.MyBatisSystemException:nestedexceptionisorg.apache.ibatis.builder.Build......
  • Unable to start activity Comandroid.content.res.Resources$NotFoundException: Str
    UnabletostartactivityComandroid.content.res.Resources$NotFoundException:StringresourceID#0x0 打开app->res->values->strings.xml文件添加<stringname="game_view_content_description">Gameview</string>......
  • 视频汇聚集中存储EasyCVR平台调用iframe地址视频无法播放,该如何解决?
    安防监控视频汇聚平台EasyCVR基于云边端一体化架构,具有强大的数据接入、处理及分发能力,可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝对接等功能。为了便于用户二......
  • hive排序函数 rank、dense_rank、row_number
    rank函数:对有序序列编号,当排序字段取值相同时编号相同,且下一条取值不同记录的编号不连续。如序列为:13,13,13,13,13,14,…对应的排序编号为1,1,1,1,1,6,…dense_rank函数:对有序序列编号,当排序字段相同时编号相同,且下一条记录的编号仍连续。如序列为:13,13,13,13,13,14,…对应的排序......
  • centos7yum安装syslog-ng
    1.安装epel源yum-yinstallhttps://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm2.安装syslog-ngyum-yinstallsyslog-ng3.修改syslog-ng配置文件vim/etc/syslog-ng/syslog-ng.conf  ......
  • linux
    :简介:如何使得CentOS7上外网Bridged桥接模式重启主机的命令:reboot重启网卡的命令:systemctlrestartnetwork.service查看ip地址的命令:ipaddrping命令可以检测网络是否畅通:pingip地址结束ping命令:ctrl+c安装ctrl+l可以清屏可以访问外网容易与局域网的其它机器ip地......
  • Tita 升级|产品细节体验优化
    功能一:企微试用版客户,超管用户增加一个【进入企微管理应用授权】的快捷入口Tita-OKR和新绩效一体化管理平台具体规则如图所示:功能二:KR负责人修改信息指数,支持目标O负责人收到提醒KR负责人≠O负责人,通知语:XXX将目标[XXXX]中关键结果[XXXXX]的信心指数由X分更......
  • 安防监控视频云存储平台EasyNVR通道频繁离线的原因排查与解决
    安防视频监控汇聚EasyNVR视频集中存储平台,是基于RTSP/Onvif协议的安防视频平台,可支持将接入的视频流进行全平台、全终端分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。为了满足用户的集成与二次开发需求,我们也提供了丰富的API接口供用户调用。有需要的用......