结构体大小的计算以及内存对其原则和修改默认对齐数

1.结构体大小的计算

          **我们都知道,不论是数组还是指针都可以计算其大小,
             而同样结构体也是可以计算大小的,
             接下来我们就深入讨论如何计算结构体的大小。**

#include<stdio.h>
#includ<stdlib.h>
struct s1
{
    char c1;
    int a;
    char c2;

};

int main()
{
    printf("%d\n", sizeof(struct s1));
    system("pause");
    return 0;
}

大家猜猜这个求出来的结果多大呢,

话不多说,直接上结果图;

是不是很疑惑呢,下面我就讲一讲结构体的大小怎么计算。
在这之前,我们先了解一个概念

2.结构体的内存对齐

首先内存对齐有以下几条规则

1.第一个成员在与结构体变量偏移量为0的地址处 (其实说白了就是和第一个成员变量的地址一样,就是从第一个成员变量的地址开始计算);
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;
对齐数=min{编译器默认的一个数,该成员的大小};
一般呢,vs中默认值=8,linux中默认值=4;
3.结构体总大小就为最大对齐数的整数倍,
!!每一个成员变量都有一个对齐数!!
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有对齐数(含嵌套结构体的对齐数)的整数倍。

下面我就分析一些具体的实例来帮大家理解;

#include<stdio.h>
#includ<stdlib.h>
struct s1
{
    char c1;     //min{1,8}=1
    int a;          //min{4,8}=4
    char c2;     //min{1,8}=1

};

int main()
{
    printf("%d\n", sizeof(struct s1));
    system("pause");
    return 0;
}

在刚刚这个例子中 他们的对齐数分别是1,4,1
首先在内存中找一个位置放入第一个成员变量,也就是c1;=>对应规则1
然后下一个成员变量的对齐数为4,所以存放这个成员变量的时候他的首地址应该放在4的整数倍处;=>对应规则2
然后最后一个是c2,他的对齐数是1,就紧接着放,可能有的同学觉得到这就结束了,但其实并不是,c2放完了以后,后边的三个字节也需要算上,而这么做的原因就要追溯到
=>规则3
所以最后就是12个字节的大小啦。
详情图解如下:

看了上面的例子我想着大家可能已经了解如何计算结构体的大小,
那么大家看一看下面的这个例子,

#include<stdio.h>
#includ<stdlib.h>
struct s2
{
    char q1;
    char q2;
    int i;

};

int main()
{
    printf("%d\n", sizeof(struct s2));
    system("pause");
    return 0;
}

不知道大家有没有发现这个例子和第一个例子是其实结构体成员都是一样的,只是顺序不一样,我还是用图来给大家讲解一下。

这里先放q1,占用一个字节,然后q2的对齐数也是1,则紧接着放,占用一个字节,i的对齐数为4,则i的首地址要放在4的倍数处,则从偏移量为4处开始放起,放完后一共8个字节,同样也是最大对齐数(4)的倍数,就是这个结构体的大小。

通过这两个例子,我们就需要想一想,在设计结构体时,怎样才能满足既要内存对齐,又要节省空间呢,那就是 !!尽可能让占用空间小的成员集中在一起。

看完这两个例子,我想大家都已经理解并且学会结构体大小的计算了吧,那么下面我们算一个结构体嵌套的大小。

#include<stdio.h>
#includ<stdlib.h>
struct  s3
{
    double a;
    char b;
    int c;
};

struct s4
{
    char d;
    struct s3 e;
    double f;
};

int main()
{
    printf("%d\n", sizeof(struct s3));
    printf("%d\n", sizeof(struct s4));
    system("pause");
    return 0;
}

大家会不会算呢,
在有结构体嵌套问题的时候,记得嵌套的结构体对齐到自己的最大对齐数的整数倍处哦,而结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

那到这可能有的人要好奇为什么要存在内存对齐呢,其原因有两点:
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存访问仅需要一次访问。

其实说白了就是用空间来换取时间是的做法

3.修改默认对齐数

最后我们再讲一个知识点,就是修改默认的对齐数;用的是#pragma这个预处理指令;

#include<stdio.h>
#includ<stdlib.h>
#pragma pack(1)  //设置默认对齐数为6
struct s5
{
    char a1;
    int i1;
    char a2;

};
#pragma pack()//取消设置的默认对齐数,还原为vs自己默认的对齐数值
int main()
{
    printf("%d\n", sizeof(struct s5));
    system("pause");
    return 0;
}

这个计算方法和上面的一模一样,就是默认对齐数改变了而已。

原文地址:https://blog.51cto.com/14339246/2410706

时间: 2025-01-15 04:17:10

结构体大小的计算以及内存对其原则和修改默认对齐数的相关文章

关于C语言中结构体大小计算

结构体大小的计算,.网上说法一大堆还都不一样分什么对齐不对齐,偏移量什么的.. 在此稍微举例简单总结下: 对齐原则:每一成员的结束偏移量需对齐为后一成员类型的倍数 补齐原则:最终大小补齐为成员中最大值的倍数 拿个题目做例子:[(开始偏移量)+此处字节 = 结束偏移量] 1 struct MyStruct 2 { 3 int i; // (0) + 4 = 4,后面一个为2,已经对齐 4 char c; // (4) + 2 = 6,后面一个为结构体,直接拆开看第一个,int=4,所以对齐为(4)

【转】彻底搞清计算结构体大小和数据对齐原则

彻底搞清计算结构体大小和数据对齐原则 数据对齐: 许多计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是 某个值K(通常是2,4或8)的倍数.这种对齐限制简化了形成处理器和存储器系统之间的接口的硬件 设计.例如,假设一个处理器总是从存储器中取出8个字节,则地址必须为8的倍数.如果我们能保 证将所有的double类型数据的地址对齐成8的倍数,那么就可以用一个存储器操作来读或者写值了. 否则,我们可能需要执行两次存储器访问,因为对象可能被分放在两个8字节存储块中. 当数据类

【c语言】结构体大小计算的例子

// 结构体大小计算的例子 // 默认对齐数为4 #include <stdio.h> union tagAAA { struct { char ucFirst;//1 short ucSecond;//2 char ucThird;//1 }half; short kk;//2 }number; struct tagBBB { char ucFirst;//1 short ucSecond;//2 char ucThird;//1 short ucForth;//2 }half; struc

结构体大小求值

 内存对齐概念,struct例子: struct stu{ char a; intb; char c; double d; char e; } 取pack(n),n,取结构体中最大成员大小m,取两个小值k, k = m< n?m:n; 取每个成员大小p,依次同k比较,取小值q = k< p?k:p; 第二步当中依次取得的值,即为内对齐标准,所谓的对齐,即此处的地址可被q整除. K值可作为外部对齐补0的依据. 当有数组的时候拆散了当普通变量存储. 下面开始计算结构体中的大小 取k值.(取pa

C/C++ sizeof函数解析——解决sizeof求结构体大小的问题

C/C++中不同数据类型所占用的内存大小 32位                 64位 char               1                    1 int                  4             大多数4,少数8 short              2                    2 long               4                    8 float               4              

程序猿之---C语言细节29(#define宏大小、空结构体大小、柔性数组不知道你见过没)

主要内容:#define宏大小.空结构体大小.柔性数组 一.#define宏大小 见例子 二.空结构体大小 根编译器有关 三.柔性数组 不常用,可看看 #include <stdio.h> #define N 4 #define STR "abcd" int main() { struct student { }stu; printf("N = %d\n", sizeof(N)); printf("num 5 memery = %d\n&quo

结构体大小的计算方法

****************************************************************************************** 结构体大小的计算方法: 1.结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍). 2.结构体大小必须是所有成员大小的整数倍. ***************************************************************************************

sizeof进行结构体大小的判断

typedef struct{    int a;    char b;}A_t;typedef struct{    int a;    char b;    char c;}B_t;typedef struct{    char a;    int b;    char c;}C_t;void main(){    char*a=0;    cout<<sizeof(a)<<endl;//4    cout<<sizeof(*a)<<endl;//1--

利用宏定义在编译阶段检查结构体大小的方法

typedef struct { char a[100]; } T_XXX; typedef struct { char a[99]; } T_QQQ; /* 检测结构体的大小是否等于特定值 */ #define SIZE_OF_TYPE_EQUAL_TO(type, size) \ static inline char size_of_##type##_equal_to_##size() \ { \ char __dummy1[sizeof(type) - size]; \ char __du