怎么修改结构体中的值占用内存怎么不对呢?

在C语言中如果只声明一个结构体类型,会占用内存【c语言吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:561,243贴子:
在C语言中如果只声明一个结构体类型,会占用内存收藏
在C语言中如果只声明一个结构体类型,会占用内存吗,请指教,谢谢了
如果用声明结构体类型在声明一个结构体变量,但并不初始化,这个结构体变量会占用内存位置吗,感谢了。
找c语言?来博为峰学C语言开发,C语言开发课程,免费训练营火热开启中!找c语言?来这里学C语言开发,抢!!!C语言开发课程试听名额,总监名师主讲.
你不会动手试试吗。
经测试,声明一个结构体与否编译出来的二进制文件大小不会有变化,所以对于第一个问题是不会声明一个变量但不使用也会占用空间,不过不排除编译器会对此进行优化(例如直接抹掉未使用过的局部变量)
声明只是告诉编译器内存怎么分布,不占空间,变量如果不优化就占
登录百度帐号推荐应用”结构体定义时,结构体本身并不占用存储空间,系统并不给结构体分配存储空间。“这句话是对的吗?_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
”结构体定义时,结构体本身并不占用存储空间,系统并不给结构体分配存储空间。“这句话是对的吗?
是不是应该为结构体申明时,就是对的了?
我有更好的答案
定义就是具有以下明确的格式,如:连接说明符 类型说明符 变量名要想知道在何时分配内存空间,首先要知道,定义和声明的含义
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包结构体A的实例占用多少内存 - 简书
结构体A的实例占用多少内存
结构体中成员按照定义时的顺序依次存储在连续的内存空间。但并不是像数组那样的连续。
内存对齐计算内存地址比较方便,内存地址会非常有规律,减小了内存寻址时间。若不对齐,
内存地址的变化非常没有规律,内存地址往往是在寄存器里计算出来的基本类型指的是像
char、int、float、double这样的内置数据类型
结构体总大小大于等于所有成员的大小之和。
结构体的总大小必须可以整除最宽基本成员。
结构体成员的地址 - 结构体的首地址 = 偏移量,必须是当前成员整数倍。
结构体尾部不足的部分,就会被填充。 整数包括正整数、0、负整数。
当只用一个成员时不存在对齐。
两者取最短原则。
};//结构体A的实例占用多少内存
int main(int argc, const char * argv[]) {
printf("A = %lu个字节\n",sizeof(a));
printf("char = %lu个字节\n",sizeof(char));
printf("short = %lu个字节\n",sizeof(short));
printf("int = %lu个字节\n",sizeof(int));
printf("float = %lu个字节\n",sizeof(float));
printf("long = %lu个字节\n",sizeof(long));
printf("double = %lu个字节\n",sizeof(double));
A = 32个字节
char = 1个字节
short = 2个字节
int = 4个字节
float = 4个字节
long = 8个字节
double = 8个字节
记叙文写作指导 1、记叙文的文体特点及其分类 记叙文是通过记述人物、事件来表明作者思想感情的一种文体。一般说来,记叙文分简单记叙文和复杂记叙文两种。前者只记一人一事,篇幅比较短小; 后者所记的人物或事件不限于一个或一件,写作方法也比较复杂。记叙文是包含面很广的文体,童话、故...
Swift语法基础(五)-- (类和结构体、属性、方法) 本章将会介绍 类和结构体对比结构体和枚举是值类型类是引用类型类和结构体的选择字符串、数组和字典类型的赋值和复制行为存储属性计算属性属性观察器全局变量和局部变量类型属性实例方法类型方法 类和结构体 类和结构体是人们构建...
哈喽,各位家人们,大家晚上好,我是养森商学院的院长,孙茂林。非常高兴,今天晚上在社群当中和我们全中国所有的养生家人以及我们海外的养生侨胞。一起去分享我们的线上课程。我本人特别高兴,因为很久没有做这样的全体养生家人的聚会和分享。大部分的时间在今年的课程线上课程的都是由我们的每...
本月在IOS培训班刚毕业,就出了swift 3.0 .好吧让我这水平差的自学吧! 咱也&高大上&一回,看看官方文档,英文看不懂啊!官方文档地址:/library/content/documentation/Swift/C...
开一家餐厅,到底怎么设置座位数呢?”“我餐厅有xx平方米,到底可以容纳多少个座位?”开店这些问题是很多人头疼的,座位数设置不合理,一方面会浪费空间,另一方面还会影响顾客体验。 还在为不知如何准确计算餐桌餐位吗?下面的方法简单实用,来试一试吧。 01 各种档次餐厅的餐位数计算...
从来美人择才子,东风小楼的花魁娘子却是价高者得许了一个商人,楼里的姑娘都说她是小时候穷怕了,才这样见钱眼开。 鸨母进门时琴娘一杯酒才送至唇边,而后杯子碎在鸨母脚边,还要再砸,鸨母已跑来抢在怀里。 “哎哟,我的小祖宗哎,这是玉的呀。” “妈妈不是刚将我卖了一大笔么,一个杯子算...
1、gem sources -l #(查看当前ruby的源) 2、gem sources --remove https://rubygems.org/ #(移除当前ruby的源)
执行结果:https://rubygems.org/ removed from sourc...
不知不觉,我的第二期#33天11本书阅读挑战训练营#又结束了。与第一期相比,第二期的节奏更慢一些,平均3天一本,自己读得不紧不慢,没有太大压力。习惯一旦养成,不用花费太大力气即可保持惯性前进。总结一下第二期的书单: 白夜行: 五星,非常精彩的故事。我想在阳光下,却只能行走在...
写作。在比伯的歌声下,心情有些激动。这是从小学到大学唯一一个从未改变的梦想。之前偶尔会想,但却从未付诸行动。 近期关注过沈式夫夫的故事,肯尼从写日记开始,美伦也不甘落后,都成为了青年作家。这有感染到我。 刚来这个大学我就从商店里挑出一本精美的日记本,准备记录我的生活,更多的...
那些风靡世界的韩剧到底都是在哪些地方拍摄的? 在以蓝色大海和洁净的自然环境为傲的庆尚南道,有很多著名电影和电视剧的摄影地。比如韩国最早的电影主题公园—山清郡黄梅山电影主题公园,电影《太极旗飘扬》的拍摄地陕川影像主题公园,电视剧《梦幻情侣》的拍摄地南海德国村等。如果你喜欢韩国...相关文章推荐
struct结构体占内存大小计算
注意:struct 的{}后面要加上 ”;“
最近和班上的一些"猿友"重新来完善或重新写以前在学校用C语言实现的数据结构,实现单链表、双向链表、循环链表、树、图等等一些数据结构。需要实现这些数据结构就必须熟练掌握C语言中的自定义类型,即结构体(s...
共用体(union)所占的字节数是最大的成员内存。
结构体(struct)类型占用的内存空间的计算方法:
首先需要确定是在32位系统,还算在64位系统
是所有成员的内存的和,但是需要注...
结构体是C语言中
struct结构体的大小计算:struct 大小,与pack的大小(在程序中显示设置#pragma pack(),vc6.0默认大小为8)、结构中最大占用有关 struct A{
这篇文章写的很好,与大家分享一下。
转载自:http://blog.csdn.net/grantxx/article/details/7577730
作者:grantxx
一个结构体变量...
一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。
一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。
假设这台机器 sizeof(char) = 1
sizeof(int) = 4
sizeof(double) = 8
枚举类型只为最宽的数据分配内存,在不同是时候,用的是同一块内存;
...
这几天在学习数据结构的时候经常会出现一个问题,就是定义了节点的结构,然后定义了指向节点的指针,但是已经定义了指针为什么就不能直接用呢,后来查了一下相关资料发现原来在新建指针的时候不会一同分配内存给他,...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)关于结构体占用空间大小总结
关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的。这道题是这样的:
在32位机器上,下面的代码中
char buff[13];
void foo(){}
typedef char* (*f)(void*);
enum{red , green, blue}
sizeof(a)的值是多少?如果在代码前面加上#pragma pack(2)呢?
我之前一直有的一个错误的观念是,编译器会将某些大小不足4字节的数据类型合并起来处理。虽然很多情况下效果也是这样的,但是,这样理解是没有把握到问题的本质,在某些情况下就会出错,比如带上#pragma pack(2)之后,那样的理解就没法分析了。
真实的情况是,数据占用内存的大小取决于数据本身的大小和其字节对齐方式,所谓对齐方式即数据在内存中存储地址的起始偏移应该满足的一个条件。比如说,一个int数据,在32位机上(以下的讨论都以此为基础)占用4个字节,如果该数据的偏移是0x,那么CPU就要先取一个char,再取一个short,最后取一个char,三次取数据组合成一个int类型。(为什么不能取一次char,然后再取一个3字节长的数据呢?这个问题从组成原理的角度考虑。32位机器上有4个32位的通用数据寄存器:EAX,EBX,ECX,EDX。每个通用寄存器的低16位又可以单独使用,叫做AX,BX,CX,DX。最后,这四个16位寄存器又可以分成8个独立的8位寄存器:AH、AL等。因此,CPU取数据时或者是一个字节AH或者AL等,或者是两个字节AX,BX等,或者是4个字节EAX,EBX等,而没法一次取三个字节的数据。)如果该数据的偏移是0x,那么CPU就可以先取一个short,然后再取一个short,两次取值完成一个int型数据的组合。但是如果偏移是0x,正好是4字节对齐的,那么CPU就可以一次取出这个int类型的数据。所以,为了提高取值速度,一般编译器都会优化数据对齐方式。优化的标准是什么呢?大小不同的各种基本数据类型的数据该怎么对齐呢?下面的表格作出了总结:
基本数据类型的偏移
基本数据类型
占用内存大小(字节)
字节对齐方式(首地址偏移)
double / long long
int / long
其中,字节对齐方式(首地址偏移),表示的是该类型的数据的首地址,应该是该类型的字节数的倍数。当然,这是在默认的情况下,如果用#pragma pack(n) 重定义了字节对齐方式,那么情况就有点复杂了。一般来说,如果定义#pragma pack(n),而按照数据类型得到的对齐方式比n的倍数大,那就按照n的倍数指定的方式来对齐(这体现了开发者可以选择不使用推荐的对齐方式以获得内存较大的利用率);如果按照数据类型得到的对齐方式比n小,那就按照前者指定的方式来对齐(一般如果不指定对齐方式时,编译器设定的对齐方式会比基本类型的对齐方式大)。下面具体到不同类型的大小时,会举一些例子。现在,只要记住这两条规律就可以了。
上面只是基本数据类型,比较简单,一般复杂的组合数据类型,比如enum(枚举)、Union(联合)、struct(结构体)、class(类)。一个个来。
数组,数组是第一个元素对齐,以后的各个元素就对齐了。
enum,枚举类型,一般来说大小为4字节,因为4个字节能够枚举个变量,大小足够了。如果不够,可能会扩充,扩充到多大没试过。
如上图所示。右边是输出,之前的输出不用管它。
Union,联合类型。联合类型的大小是最长的分量的长度,加上补齐的字节。这里容易有一个谬误,有人说补齐的字节是将联合类型的长度补齐为各分量基本类型的倍数,这个说法在默认的字节对齐(4字节或8字节)中没问题,但是当修改对齐方式之后就有问题了。先看一下默认的情况。
char buff[13];
上述定义的联合体,在默认的字节对齐方式中,大小为16字节。首先计算得到联合最长的分量长度是sizeof(char)*13=13字节。但是13不是sizeof(int)的倍数,所以将13扩充至16,最终得到sizeof(t)=16字节。
这是在默认情况下,扩充后的大小是各分量基本类型大小的倍数。但是,如果指定对齐方式为#pragma pack(2),那情况就不一样了。此时得到的最长分量还是13字节,不过扩充时不是按照4字节的倍数来算,而是按照2的倍数(pragma pack指定的)来算。最终得到大小为14字节。
Union联合体还是比较简单的,因为不牵涉到各分量的起始偏移地址对齐的问题。下面来看看struct结构体。首先要注意的是,struct和class在C++中其实是一样的,struct也可以有构造函数,析构函数,成员函数和(private、protected、public)继承。两者的区别在于class默认的成员类型是private,而struct为public。class默认的继承方式为private,而struct为public。其实核心是struct是数据聚集起来,便于人访问,所以默认的是public,而class是封装,不让人访问,所以是private。
其次要注意的是struct或class中定义的成员函数和构造和析构函数不占整体的空间。如果有虚函数的话,会有4个字节的地址存放虚函数表的地址。
由于struct和class的相同,所以下面都已struct为例进行讨论。
struct占用内存大小的计算有两点,第一点是各个分量的偏移地址的计算,第二点是最终整体大小要进行字节对齐。
char a[15]; //占15个字节,从0开始偏移,所以下面的int是从15开始偏移
//偏移量 0x15+1=16
cout&&sizeof(s1)&& //结果为20字节
char a[15]; //
//偏移量 16字节
//偏移量 21字节
}s2; //结果为21字节,按最大基本类型对齐,补充到24字节
cout&&sizeof(s2)&& //结果为24字节
char a[15];
//偏移量 16字节
//偏移量 24字节
cout&&sizeof(s3)&& //结果为32字节
上面几个例子的说明。以s3为例。首先,从偏移量为0的地方开始放char,连续放15个,每个占1字节。则int x对应的偏移量是第15个字节,按照上面表格的说明,int类型的偏移量应该能够整除int类型的大小,所以编译器填充1个字节,使int x从第16个字节开始放置。x占4个字节,所以double b的偏移量是第20个字节,同理,20不能整除8(double类型的大小),所以编译器填充4字节到第24个字节,即double
b从第24个字节开始放置。最终结果为15+1+4+4+8=32字节。其他的类型同此分析。
不过,上面这个例子还不够明显,再举一个需要最后补充字节的例子。
char a[15];
//偏移量 16字节
//偏移量 24字节
//偏移量 32字节
}s3;//共33字节,按最大基本类型对齐,补充到40字节(整除8)
cout&&sizeof(s3)&& //结果为40字节
上面的例子中,最后多了一个char型数据。导致最后得出的大小是33字节,这个大小不能够整除结构体中基本数据类型最大的double,所以要按能整除sizeof(double)来补齐,最终得到40字节。
也即,凡计算struct这种结构体的大小,都分两步:第一,各个分量的偏移;第二,最后的补齐。
下面来看看如果主动设定对齐方式会如何:
#pragma pack(push)
#pragma pack(2)
char a[13]; //占13个字节,从0开始偏移,所以下面的int是从13开始偏移
//偏移量 0x13+2=14,不按整除4来偏移,按整除2来偏移
cout&&sizeof(s4)&& //结果为18字节
char a[13]; //
//偏移量 14字节
//偏移量 18字节
}s5; //结果为19字节,按2字节对齐,补充到20字节
cout&&sizeof(s5)&& //结果为20字节
char a[13];
//偏移量 14字节
//偏移量 18字节
//偏移量 26字节
}s6;//共27字节,按2字节对齐,补充到28字节(整除8)
cout&&sizeof(s6)&& //结果为28字节
#pragma pack(pop)
上面的代码分析跟之前是一样的,只不过每次改变了对齐方式,结果如注释所云。注意,跟之前的例子相比,为了体现效果,char型数组大小改为13了。
上面提到的对齐方式,也符合之前说到对#pragma pack(n)的两条规律。
如果#pragma pack(1)那结果如何,那就没有对齐了,直接将各个分量相加就是结构体的大小了。
上面的分析,可以应付enum、union、struct(或class)各种单独出现的情况了。下面再看看组合的情况。
struct ss0{
char a[15]; //占15个字节,从0开始偏移,所以下面的int是从15开始偏移
//偏移量 0x15+1=16
cout&&sizeof(s1)&& //结果为20字节
struct ss1
char a[15]; //
//偏移量 16字节
//偏移量 21字节
}s2; //结果为21字节,按最大基本类型对齐,补充到24字节
cout&&sizeof(s2)&& //结果为24字节
char a[15];
//偏移量 16字节
//偏移量 24字节
//偏移量 32字节
}s3;//共33字节,按最大基本类型对齐,补充到40字节(整除8)
cout&&sizeof(s3)&& //结果为40字节
//偏移0,1字节
struct ss0//偏移1+3=4,20字节
//偏移24, 1字节
struct ss1//偏移25+3,24字节
//偏移52,1字节
struct ss2//偏移53+3,40字节
//偏移96,1字节
}s7;//共97字节,不能整除sizeof(double),所以补充到104字节
cout&&&here:&&&sizeof(s7)&&
组合起来比较复杂。不过也有原则可循。首先,作为成员变量的结构体的偏移量必须是自己最大成员类型字节长度的整数倍。其次,整体的大小应该是结构体中最大基本类型成员的整数倍。结构体中字节数最大的基本数据类型,应该包括内部结构体的成员变量。根据这些原则,分析一下上面的结果。第一个struct ss0 b的大小之前已经算过,是20字节,其偏移量是1字节,因为strut ss0中最大的数据类型是int类型,故而strut
ss0的偏移量应该能够整除sizeof(int)=4,所以偏移量为4。同理,可得strut ss1。然后是strut ss2,其偏移量是53字节,但是strut ss2最大的成员变量的double类型,故而其偏移量应该能够整除sizeof(double),补充为56字节。最后得到97字节的结构体,而struct s7 最大的成员变量是struct ss2中的double,所以struct s7应该按8字节对齐,故补充到能够整除8的104,所以结果就是104字节。
如果将struct ss2去掉,则struct s7中最大的数据类型就是int,最终结果就应该按sizeof(int)对齐。如下所示:
//偏移0,1字节
struct ss0//偏移1+3=4,20字节
//偏移24, 1字节
struct ss1//偏移25+3,24字节
//偏移52,1字节
//struct ss2//偏移53+3,40字节
//偏移53,1字节
}s7;//共54字节,不能整除sizeof(int),所以补充到56字节
cout&&&here:&&&sizeof(s7)&&
上述结果是正确的,可知我们的分析是正确的。
如果将struct s7用#pragma pack(2)包围起来,其他的不变,可以推测,结果将是92字节,因为其内部各结构体成员也都不按自己内部最大的数据类型来偏移。代码如下,经测试,结果是正确的。
struct ss0{
char a[15]; //占15个字节,从0开始偏移,所以下面的int是从15开始偏移
//偏移量 0x15+1=16
cout&&sizeof(s1)&& //结果为20字节
struct ss1
char a[15]; //
//偏移量 16字节
//偏移量 21字节
}s2; //结果为21字节,按最大基本类型对齐,补充到24字节
cout&&sizeof(s2)&& //结果为24字节
char a[15];
//偏移量 16字节
//偏移量 24字节
//偏移量 32字节
}s3;//共33字节,按最大基本类型对齐,补充到40字节(整除8)
cout&&sizeof(s3)&& //结果为40字节
#pragma pack(push)
//偏移0,1字节
struct ss0//偏移1+1=2,20字节
//偏移22, 1字节
struct ss1//偏移23+1,24字节
//偏移48,1字节
struct ss2//偏移49+1,40字节
//偏移90,1字节
}s7;//共91字节,不能整除2,所以补充到92字节
cout&&&here:&&&sizeof(s7)&&
#pragma pack(pop)
下面就可以来分析本文开头部分提出的那个变量了。再录入如下:
char buff[13];
void foo(){}
typedef char* (*f)(void*);
enum{red , green, blue}
int i 的偏移是0,占据4个字节, union U u本身的大小是16字节,偏移是4,满足整除4字节的要求。(注意,这里刚好是偏移符合的情况,如果在int i后面定义一个char,则此处要按4字节对齐,需要补充3个字节。)color的大小是4字节,偏移量是20,满足整除sizeof(int)的要求,所以不用填充。如果color前面再定义一个char,则此处要补充到4字节对齐。综上,最终得到的A的大小是4+16+4=24字节。
如果加上参数#pragma pack(2),则union U u的大小编程14字节,最终得到class A的大小是22字节。
上面的例子不够过瘾,因为class A中出现的基本类型正好不超过int,下面看看这个例子。
//偏移0,4字节
char buff[13];
}u; //偏移4,不能整除sizeof(double),所以偏移需要补充到8,大小 16字节
void foo(){}
typedef char* (*f)(void*);
//偏移24,大小1字节
enum{red , green, blue}//偏移25,补充到28,大小4字节
//偏移32,大小1字节
}a;//大小33字节,不能整除sizeof(double),补充到40字节
上面的例子中,上面的例子既有内部偏移的对齐,又有最后的补齐。可见struct A补齐时需要对齐的是union U u的成员double i,所以最后是补充到了40字节。
当然,上面所有的分析都可以通过查看成员变量偏移位置的方法来判断。方法如下:
#define FIND(structTest,e) (size_t)&(((structTest*)0)-&e)
//偏移0,4字节
char buff[13];
}u; //偏移4,不能整除sizeof(double),所以偏移需要补充到8,大小 16字节
void foo(){}
typedef char* (*f)(void*);
//偏移24,大小1字节
enum{red , green, blue}//偏移25,补充到28,大小4字节
//偏移32,大小1字节
}a;//大小33字节,不能整除sizeof(double),补充到40字节
//.........省略..........................
cout&&&i 的偏移:&&&FIND(A, i)&&
cout&&&u 的偏移:&&&FIND(A, u)&&
cout&&&color 的偏移:&&&FIND(A, color)&&
FIND定义的宏即可用来查看成员变量的偏移情况。跟之前的分析是相符的。
最后补充一点,编译器默认的#pragma pack(n)中,n的值是有差异的,我上面测试的结果大多都在VC++和G++中测试过,结果相同。只有少部分示例没有在G++中测过。所以,主要的平台,以VC++为准。据说VC++默认采用的8字节对齐。不过,也不好验证,因为当结构体中最大为int类型时,根据前面的两条对齐准则,最终结果会按照int类型来对齐。当结构体中最大为double类型时,此时基本数据类型的对齐方式,与默认的8字节对齐方式相同,也看不出差异。既然如此,也就不用特意去纠结VC++中采用的是几字节对齐方式了。更多的精力应该放在思考怎么样组织结构体,才能使得空间利用效率最高,同时又有较高的访问效率。
补充:类或结构体的静态成员变量不占用结构体或类的空间,也就是说sizeof出来的大小跟静态成员变量的大小无关。在最后补齐字符的时候,也与静态成员变量无关。比如:
static double y4;
double yy::y4;
上述结构体的大小不包括是static double y4变量的空间。最后补齐也是按照4字节补齐,而不是按照8字节补齐。
这一点应该比较容易想到,因为类或结构体的静态成员变量是存储在全局/静态存储区的,而类或结构体是存储在栈上的,两者在内存占用上没有关系也是显而易见的。
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?

我要回帖

更多关于 结构体怎么用 的文章

 

随机推荐