关于结构体内存问题

C语言 码拜 10年前 (2015-05-11) 1465次浏览 0个评论

以下是俩个定义的结构体,在内存中所占空间大小不是一样的吗?
struct node
{
    int x;
    char y;
    double z;
}

struct node
{
    int x;
    double y;
    char z;
}

结构体类型不分配存储空间,结构体变量分配必要的存储空间
又不是共用体的各成员共享一段内存

那请问上面俩结构体所占空间大小是一样的吗??
如果不一样,是后者大吗?

已找到 还是应该自己先想办法 
每个单元多大取决于结构体中最大基本类型的大小。
那么
这俩个结构体每个单元最大都是double类型 16个字节
对于第一个
第一个单元可以存放int和char 第二个单元存放double 这样就是16*2=32字节
对于第二个
第一个单元存放int后 剩下不够double 所以有第二个单元全是double 无剩余 所以需要第三个单元 这样就是 16*3=48字节
你的理解可以说对了一半,你还得看编译器的默认对齐大小
在我以往的编程经验里,vs2005和我现在在用的vs2010,默认对齐大小是4字节
所以你的结构体如果放到我的编译器中的话,两个结构的大小都是一样的16字节

第一个 int 占4字节,第二个 char 占1字节,编译器按默认4字节对齐自动补齐变为4字节,第三个 double 占8字节,是4字节的整数倍,不用补齐,所以合共大小是16字节

第二种定义方式原理一样,所以结果也是16字节大小

5分
#include "stdafx.h"

struct node1
{
    int x;
    char y;
    double z;
};

struct node2
{
    int x;
    double z;
    char y;
};

int main()
{
    int n1 = sizeof(node1);
    int n2 = sizeof(node2);

    return 0;
}

断点时局部变量值:
n2 24 int
n1 16 int

原来我也理解错了,第二种定义方式按8字节对齐了

5分
在C和C++中成员变量的声明顺序和它在内存中的位置的前后关系是一致的,但不一定连续存储,还要考虑字节对齐的问题,以及C++中的对多态的支持,而添加的多余数据类型。
10分
有一句话没看太懂: “又不是共用体的各成员共享一段内存”

不管这句话了。
这个问题还比较基本的。涉及到了一个字节对齐的问题。

上面已经有仁兄提到了,这个还是要看你的编译器使用的对齐方式,当然这个对齐方式也可以自己设置。
大部分编译器默认的都是4字节对齐,如果是4字节对齐的话,上面两个结构体的大小都是16。(其中char类型补齐4字节)。
如果设置8字节对齐,就如你所说的,第一个大小为16(8+8),其中x和y共同占用8个字节,第二个为24(8+8+8),x和z分别占8个字节。

另外,提一点,在实际中,测试发现,字节的对齐方式应该与机器的位数有一定的关系的。
环境 linux、g++编译器
32位系统上(默认4字节对齐),最大是4字节对齐
64未系统上(默认8字节对齐),最大是8字节对齐
设置过大的话,是无效的,编译器还是默认对齐进行编译。

————————-
个人见解,共同学习。

10分
仅供参考:

#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//
1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储

 

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

 

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.

10分
数据成员对齐 必须不一样 第一个16 第二个24

最长的是double 8所以规格是8

第一个就是
xxxx y- – –
zzzz zzzz

第二个就是
xxxx- – – –
yyyyyyyy
z— – – – –


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于结构体内存问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!