
1题
答案是D
因为rt 是结构体变量,不是指针变量,所以不能使用->
2题
结构体大小是变量大小之和
char num[6] 6
int s[4] sizeof(int)4
double ave sizeof(double) 1
所以大小为6 + sizeof(int)4 +sizeof(double) 1
由于不同环境int double的大小不同 所以这里我不能答复你具体是多少
可以举个例子
32位的 window xp vc60开发环境
int 类型为4字节
double 类型为8字节
所以结构体大小为 6+44+8=30
#include<stdioh>
int main()
{
struct node
{
int data;
struct node next;
}snode;
struct node p;
p=&snode;
return 0;
}
上面定义了一个单链表结构体node,它有2个变量,其中p就是指针变量
p=&snode就是让指针p指向结构体snode的首地址,这样p就能对snode的元素data进行 *** 作
如p->data=5
另外,虚机团上产品团购,超级便宜
在说计算方式之前先讲讲几个概念一个是 偏移量 还有一个是 内存对齐 。先说偏移量,百度百科对于它的定义是这样:把存储单元的实际地址与其所在段的段地址之间的距离称为段内偏移,也称为“有效地址或偏移量”。在结构体里面大概是指结构体变量中成员的地址和结构体变量地址的差。然后再说一下内存对齐这个概念:内存中存放基本类型数据时,计算机的系统会对其位置有限制,系统会要求这些数据的首地址的值是某个数的倍数,而这个数被称为该数据类型的对齐模数。虽然ANSI C标准中没有强制规定相邻声明的变量内存中要相邻,但是编译器会自动帮你处理这个问题,也就是相邻变量之间可能会填充一些字节。因此在这个问题上又有了编译器的区别。
那我们先来讲讲结构体变量在微软的编译器的对齐吧
1结构成员的首地址要是其最宽的基本类型成员的整数倍。编译器在给结构体分配内存的时候先找到最宽的基本成员,然后再在内存中寻找地址,并将这个最宽的基本数据类型的大小作为对齐模数
2结构体每一个成员相对于首地址的偏移量是成员大小的整数倍,如果没有达到这个要求,编译器会自动填加字节。编译器在为结构体成员开辟内存的时候会先检查开辟内存的首地址与结构体变量的首地址之间的偏移量,如果是成员体的整数倍那么就存放这个变量,不然的话就在这个成员和上一个成员之间填充字节,以达到整数倍的目的
3结构体所占的总内存大小要是最大成员体大小的整数倍,如果不是,那么编译器会在末尾补充字节。结构体的最后一个成员,不仅要满足前两条原则,最后一条准则也要满足。
接下来来看看几个例子。
这个结构体在VS 2017下的sizeof的运算结果是12。那么根据上面的对其规则我们来对其进行计算。
首先是char a。char大小是1,相对于首地址的偏移量是0,然后是int i。int i的大小是4,相对于首地址的偏移量是1,但是1不是4的整数倍,所以编译器会自动在char a和int i之间填充字节字节。所以in i的偏移量是4。而之后的float b大小4偏移量就是int i的偏移量加上int i的大小故float b的偏移量大小就是8,而8正好是4的倍数那么就不会有字节填充。而结构体的大小也就自然是最后8+4=12了
从这里也可以看出结构体大小等于最后一个成员体的大小加上它的偏移量。
那么我们再来看一个例子
那么我们再利用之前的算法来对其进行运算,int i的大小是4偏移量是0,int c 的大小是4偏移量是4,double b的大小是8,偏移量是8。char a的大小是1 ,偏移量是16。那么这个结构体的变量的大小就是16+1=17吗?答案肯定不是这样的。在VS的sizeof的运算下这个的结果是24,为什是24呢,那么这之前说的最后一条原则就要用上了。结构体的大小确实是等于最后一个成员的偏移量加上最后一个成员的大小,但是如果这个结构不满足是结构体中最大成员大小的整数倍这个条件那么,编译器会自动在最后填充字节使其满足,也就是说,虽然我们计算出的结果是17但是17并不是8的倍数,所以编译器自动在最后填充字节使其成为8的倍数,即自动扩充成24、
那我们再来说一下GCC编译器下的模式。GCC编译器在Windows环境下用的会比较少,主要在Linux平台下使用GCC编译器就不遵守微软的编译器下的一些准则了,比如之前 说过的对齐模数。微软的编译器下的对齐模数是结构体成员中最大的大小而在GCC编译器下对齐模数最大只能是4。这就意味着对齐模数只能是1,2,4中的一个。因此之前讲过的在微软编译器下的的一些原则会有些不同。之前讲过的成员的首地址的偏移量要是成员大小的整数倍在这里就有点区别了。在GCC中如果成员大小小于等数4那么继续按照之前的标准就好了,但如果大于4,则结构体每个成员相对于结构体首地址的偏移量只能按照是4的整数倍来进行判断是否添加填充。来看一个简单的例子。
在这个例子中,如果是按照微软的编译器的话计算的结构应该是16,但是在GCC编译器下是12。道理就是之前讲的。
虽然理论上如此但是我自己在试的时候发现上面的运算结果是16,没错是16而不是12!为什么呢?难道是这个理论错了么,当然不是。我们可以尝试在GCC下计算一下sizeof(int )(是int 而不是int)。你会发现结果是8(如果是sizeof(int)那么结果结果就是4),输出结果是8那就解决了我们的疑惑。 64位系统的对其长度默认是8而32位的才是4 。这就合理解释了为什么计算结果是16而不是12。
对齐模数的选择只能是基于基本数据类型,所以对于结构体嵌套结构体就不能这么,至于其的计算方式之后再补充
以上就是关于c语言结构体问题全部的内容,包括:c语言结构体问题、怎样输出一个复杂的头文件中的所有结构体名以及它的大小 具体代码、C语言中结构体字节的计算方式等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)