结构体的基本概念以及内存对齐

我们都知道C语言中有很多自定义类型,像数组,指针,都是C语言中的自定义类型。但今天我们要说的不是这个,我们要聊另外一种自定义类型,叫做结构体,结构体是C语言中很重要的一个概念,用结构体甚至可以实现面向对象的机制,所以他有非常重要的用途。

一、结构体的基本概念

首先来看看结构体的基本概念:结构是一些集合的值,这些值称为成员变量,每个成员变量可以是不同的值。

结构体的声明:

struct person
{
    char name[20];
    short age;
    char sex[2];
}p;

结构体声明大概就长上面这个样子,person是他的标签,当然, 你也可以省略标签,那样的话就叫做匿名结构体,当然,我不建议你省略,因为那样的结构体可能会给你添不必要的麻烦。p是这个结构体的名字,通常用.操作符来对成员变量进行操作。

成员变量的类型多种多样,可以是标量,可以是数组,也可以是指针,甚至是其他结构体,当然不能是两个结构体的成员变量是互相定义,那样是不可行的,想想都知道,那会陷入无穷无尽的类似于递归的情形之中。函数也不可以作为成员变量放在结构体里。还有,结构体不可以直接自引用,原因和两个结构体互相调用原因相同,正确的自引用方式是通过指针。

然后我们来聊聊结构体的初始化和赋值,结构体和数组在初始化的时候有一些类似的地方,比如长这样:

#include<stdio.h>

struct A
{
    int i;
    char c;
    short s;
}a = 
{
    {3},
    { 'a' },
    {6}
};

int main()
{
    struct A *p = &a;
    printf("%c,%d,%d\n", a.c, a.i, a.s);
    p->i = 5;
    p->s = 2;
    p->c = 'b';
    printf("%c,%d,%d\n", (*p).c, (*p).i, (*p).s);
    return 0;
}

上面跟在a后面的代码块就是初始化操作,我们首先打印了初始化的值,然后用指针操作的方式对结构体A进行了重新赋值

二、结构体的内存对齐

首先要抛出一个问题:为什么存在内存对齐?
你可以搜索到的很多资料都会这么告诉你:
1.平台原因:并非所有硬件都能访问任意地址上的任意数据,有些硬件只能在特定的地址取出特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构应该尽可能地在自然边界上对齐,尤其是栈。原因在于,对于未对齐的数据,处理器需要两次访问内存(因为部分可能访问不到),而对齐的数据只需要访问一次。
所以内存对齐是一个做过权衡后的用空间来换取时间的做法。

所以在定义结构体的时候应该尽量将小字节的数据定义在一起

结构体对齐规则:
1.第一个成员变量的偏移地址为0;
2.其他成员变量要默认对齐到对齐数的整数倍地址处,对齐数=编译器默认大小和该成员变量之间的较小值。VS中编译器默认的对齐数大小是8,Linux中的默认值为4
3.结构体总大小必须是最大对齐数的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。

看完理论,来实践一下:

struct A
{
    int i;
    char c;
    short s;
}a;

struct B
{
    char a;
    short b;
    double d;
}b;

int main()

{
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(b));
    return 0;
}

猜猜看这两个结构体大小是多少?(Win32下VS的运行环境
答案是:8和16,你算对了吗?
先来看A结构体:
首先,在这个运行环境下,int的大小是4,char的大小是1,short的大小是2,4+1+2=7,这其中最大的是4,所以对齐数是4,VS编译器的默认对齐数是8,所以需要补全到8,并且4可以被8整除,由此可得最终答案是8。
再来看B结构体:
char是1,short是2,double是8,1+2是3,再加8偏移量不符合编译器默认的对齐数,所以double的存储是从偏移量为8的地方开始存储,相加得16,而8也可以被16整除,所以最终结果是16。

另外,在C语言之中,使用预编译指令#pragmma pack(n)可以修改编译器默认的对齐数大小,n是程序员指定的对齐数大小,但是只可以指定2^n的数字,n从0开始,并且不能超过编译器默认的最大数字,否则仍为编译器默认对齐数。

好了,这篇文章就聊到这里,有兴趣的朋友可以自己试试在结构体里定义数组,定义结构体之后内存对齐的大小,依据上面给出的规则,你都可以得到正确答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值