结构体类型的长度计算
问一个问题:1:计算下列各结构体类型的长度。①structA{inta;doubled;};长度:12个字节②structB{chars[10];inta;Ak;};长度...
问一个问题:
1:计算下列各结构体类型的长度。
①struct A{int a; double d;}; 长度: 12个字节
②struct B{char s[10];int a ; A k;}; 长度: 26个字节
这两个题目不知道怎么计算?
请教大牛!最好讲得详细点,本人菜鸟。。。
自己刚才查找了一些资料,好像弄懂了这个问题,答案得到是12和28。
在结构体A中,int占4个字节,double占8个字节,而int和double数据自身对齐值都为4,因此存储为(4)+(4)(4),结构体A的长度即为12个字节
在结构体B中,按照结构中占用空间最大的数据类型进行对齐,由于A k和int的存在,以4字节为对齐值,这样char占用10个字节,int占用4个字节,A k则12个字节,存储时为(4)(4)(4)+(4)+[(4)+(4)(4)],共28个字节长
不知道是否能这样解释,请大家指正。 展开
1:计算下列各结构体类型的长度。
①struct A{int a; double d;}; 长度: 12个字节
②struct B{char s[10];int a ; A k;}; 长度: 26个字节
这两个题目不知道怎么计算?
请教大牛!最好讲得详细点,本人菜鸟。。。
自己刚才查找了一些资料,好像弄懂了这个问题,答案得到是12和28。
在结构体A中,int占4个字节,double占8个字节,而int和double数据自身对齐值都为4,因此存储为(4)+(4)(4),结构体A的长度即为12个字节
在结构体B中,按照结构中占用空间最大的数据类型进行对齐,由于A k和int的存在,以4字节为对齐值,这样char占用10个字节,int占用4个字节,A k则12个字节,存储时为(4)(4)(4)+(4)+[(4)+(4)(4)],共28个字节长
不知道是否能这样解释,请大家指正。 展开
4个回答
展开全部
不能像楼主这样解释,计算结构体的长度,不能忽略一个参数:
#pragma pack(8); //这个8是结构体默认的对齐参数,其作用是:
1>当结构体中有变量类型占的长度比这个大,那么该结构的对齐参数就是8;
2>如果结构体中成员的类型都比这个默认值小,那么该结构体的对齐参数就是该结构体中占用空间最长的成员变量的长度,如instruct A{char a1;char a2};的对齐长度是1(字符变量占1个字节)
根据楼主的输出,楼主的运行环境pack(4),因为A中double占的字符大于4,所以结构体A的对齐参数为4,那么结果就是4+4+4,实际后面两个4是存一个double数据;第二题int a;已经等于4,所以对齐变量为4。
当知道对齐规则后,那么内存是怎么排列的呢?
定义变量的时候先找到一个内存地址,根据计算机的内部结构(我还不是很清楚),会选用一个可用的,而且对对齐变量求余为0的地址作为存储该结构体的地址。
如2题既然对齐变量为4,那么一定会选一个4的整数倍的地址作为存储这个结构体的起始地址,
然后是10个char类型,占10个字节,此时,下面的地址已经不能整除4了,比如8+10=18已经不能整除4,所以会空2个字节,从20开始存储int,正好4个字节,地址变为24,能被4整除,也就是char s[10]和int a,占用了12(有2个空字节)+4=16个字节,由于int a后的地址能被4整除,所以A K,的长度就是A的长度为12,所以B的长度为28。
你可以#pragma pack(8);来修改默认的对齐参数来测试。
#pragma pack(8); //这个8是结构体默认的对齐参数,其作用是:
1>当结构体中有变量类型占的长度比这个大,那么该结构的对齐参数就是8;
2>如果结构体中成员的类型都比这个默认值小,那么该结构体的对齐参数就是该结构体中占用空间最长的成员变量的长度,如instruct A{char a1;char a2};的对齐长度是1(字符变量占1个字节)
根据楼主的输出,楼主的运行环境pack(4),因为A中double占的字符大于4,所以结构体A的对齐参数为4,那么结果就是4+4+4,实际后面两个4是存一个double数据;第二题int a;已经等于4,所以对齐变量为4。
当知道对齐规则后,那么内存是怎么排列的呢?
定义变量的时候先找到一个内存地址,根据计算机的内部结构(我还不是很清楚),会选用一个可用的,而且对对齐变量求余为0的地址作为存储该结构体的地址。
如2题既然对齐变量为4,那么一定会选一个4的整数倍的地址作为存储这个结构体的起始地址,
然后是10个char类型,占10个字节,此时,下面的地址已经不能整除4了,比如8+10=18已经不能整除4,所以会空2个字节,从20开始存储int,正好4个字节,地址变为24,能被4整除,也就是char s[10]和int a,占用了12(有2个空字节)+4=16个字节,由于int a后的地址能被4整除,所以A K,的长度就是A的长度为12,所以B的长度为28。
你可以#pragma pack(8);来修改默认的对齐参数来测试。
图为信息科技(深圳)有限公司
2021-01-25 广告
2021-01-25 广告
边缘计算可以咨询图为信息科技(深圳)有限公司了解一下,图为信息科技(深圳)有限公司(简称:图为信息科技)是基于视觉处理的边缘计算方案解决商。作为一家创新企业,多年来始终专注于人工智能领域的发展,致力于为客户提供满意的解决方案。...
点击进入详情页
本回答由图为信息科技(深圳)有限公司提供
展开全部
这个问题确实有点纠结,但不是没有规律。
首先求字节长度用sizeof(...)
#include<stdio.h>
int main()
{
//using std::cout;
struct A{
int a;
double d;
};
struct B{char s[10];int a ; A k;};
int a=sizeof(A);
int b=sizeof(B);
printf("%d%d",a,b);
}
输出16,32而不是12,26.
默认对齐,应该是以struct的最大元素为对齐基数,也就是(double)8的倍数(第二个b为16的倍数。
正如三楼”所说在定义结果体的时候最好把相同类型的成员放到一起,可以节省空间“
具体LZ可以去试试。
首先求字节长度用sizeof(...)
#include<stdio.h>
int main()
{
//using std::cout;
struct A{
int a;
double d;
};
struct B{char s[10];int a ; A k;};
int a=sizeof(A);
int b=sizeof(B);
printf("%d%d",a,b);
}
输出16,32而不是12,26.
默认对齐,应该是以struct的最大元素为对齐基数,也就是(double)8的倍数(第二个b为16的倍数。
正如三楼”所说在定义结果体的时候最好把相同类型的成员放到一起,可以节省空间“
具体LZ可以去试试。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
这个问题很是纠结啊
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
typedef struct __tagA
{
int a;
char b;
char c;
}A,*PA;
typedef struct __tagB
{
char b;
int a;
char c;
}B,*PB;
int main(int argc, char* argv[])
{
A a;
B b;
int sizeA = sizeof(A);
int sizeB = sizeof(B);
printf("sizeof A is %d \nsizeof B is %d\n",sizeA,sizeB);
printf("%d,%d,%d,%d\n",sizeof(a),sizeof(a.a),sizeof(a.b),sizeof(a.c));
printf("%d,%d,%d,%d\n",sizeof(b),sizeof(b.a),sizeof(b.b),sizeof(b.c));
system("pause");
return 0;
}
测试一下就知道纠结在什么地方了,总而言之,计算结构体的长度唯一的办法是sizeof(...)。
在定义结果体的时候最好把相同类型的成员放到一起,可以节省空间
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
typedef struct __tagA
{
int a;
char b;
char c;
}A,*PA;
typedef struct __tagB
{
char b;
int a;
char c;
}B,*PB;
int main(int argc, char* argv[])
{
A a;
B b;
int sizeA = sizeof(A);
int sizeB = sizeof(B);
printf("sizeof A is %d \nsizeof B is %d\n",sizeA,sizeB);
printf("%d,%d,%d,%d\n",sizeof(a),sizeof(a.a),sizeof(a.b),sizeof(a.c));
printf("%d,%d,%d,%d\n",sizeof(b),sizeof(b.a),sizeof(b.b),sizeof(b.c));
system("pause");
return 0;
}
测试一下就知道纠结在什么地方了,总而言之,计算结构体的长度唯一的办法是sizeof(...)。
在定义结果体的时候最好把相同类型的成员放到一起,可以节省空间
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
计算方法:
运算符sizeof可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1; sizeof(int) = 4。基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小。
C语言中的构造数据类型有三种:数组、结构体和共用体。
数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数。
结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体:
struct stu1
{
int i;
char c;
int j;
};
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 二、结构体大小必须是所有成员大小的整数倍。
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
再看一个满足第一条,不满足第二条的情况
struct stu2
{
int k;
short t;
};
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小。对比下面两种定义顺序
struct stu3
{
char c1;
int i;
char c2;
}
struct stu4
{
char c1;
char c2;
int i;
}
虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?只需把其展开即可。但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。看下面的例子:
struct stu5
{
short i;
struct
{
char c;
int j;
} ss;
int k;
}
结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。
如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的GCC。其他平台的C编译器可能会有不同的处理。
运算符sizeof可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1; sizeof(int) = 4。基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小。
C语言中的构造数据类型有三种:数组、结构体和共用体。
数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数。
结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体:
struct stu1
{
int i;
char c;
int j;
};
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 二、结构体大小必须是所有成员大小的整数倍。
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
再看一个满足第一条,不满足第二条的情况
struct stu2
{
int k;
short t;
};
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小。对比下面两种定义顺序
struct stu3
{
char c1;
int i;
char c2;
}
struct stu4
{
char c1;
char c2;
int i;
}
虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?只需把其展开即可。但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。看下面的例子:
struct stu5
{
short i;
struct
{
char c;
int j;
} ss;
int k;
}
结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。
如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的GCC。其他平台的C编译器可能会有不同的处理。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询