浅谈C语言对齐

发布时间:2024年01月04日

这一次要介绍的是一个gcc编译参数:

__attribute__((__aligned__(n)))

这里,我们将不讨论结构体内部的对齐问题。

我们将分为三个部分介绍这个编译参数——针对变量类型结构体

针对变量

首先我们看一个简单的例子:

#include <stdio.h>

int main(void)
{
  int i __attribute__((__aligned__(64))) = 10;
  printf("%lx %lu\n", (unsigned long)&i, sizeof(i));
  return 0;
}

通过编译后,执行这个程序,结果如下:

7fffadbc43c0 4

可以看到,变量i的内存地址的后6位为0。而变量i占用的内存大小为4个字节。

这说明,对齐使得i的内存起始地址向64字节对齐了,但不影响其内存大小。

针对类型

何为针对类型呢?我们来看下面这个例子:

#include <stdio.h>

typedef int Int __attribute__((__aligned__(64)));

int main(void)
{
  Int i = 10;
  printf("%lx %lu\n", (unsigned long)&i, sizeof(i));
  return 0;
}

编译后运行,发现与上例结果相似,变量i的起始地址为64字节对齐。

那么如果我们修改一下,变为如下代码呢?

#include <stdio.h>

typedef int Int __attribute__((__aligned__(64)));

int main(void)
{
  Int i[2] = {1, 10};
  printf("%lx %lu\n", (unsigned long)&i, sizeof(i));
  return 0;
}

此时,编译代码就会报错,遇到类似如下报错提示:

错误:数组元素的对齐边界比元素大小还要大

这话什么意思呢?

简单来说,数组i的每个元素要向64字节对齐,而每个数组元素所占内存大小为4字节,那么就会发现,元素之间有空隙。这就是这个报错的意思,数组元素不连续了。

针对结构体

最后,我们来看看结构体的一些行为是怎样的。示例如下:

#include <stdio.h>

struct test {
  long a;
  long b;
  long c;
  long d;
  long e;
  long f;
  long g;
  long h;
  long i;
} __attribute__((__aligned__(64)));

int main(void)
{
  struct test t;
  printf("%lx %lu\n", (unsigned long)&t, sizeof(t));
  return 0;
}

编译代码,然后运行,结果如下:

7ffe525cce40 128

可以看到,结构体变量t内存起始地址依旧保持了64字节对齐,且结构体变量的大小也变为64字节的整数倍了。

此时假设我们将代码中t定义的语句改为:

struct test t[2];

依旧可以通过编译。

可见,空隙问题对于结构体是不存在影响的,因为编译器只需要调整结构体大小就可以将空隙自动填平了。

文章来源:https://blog.csdn.net/weixin_40960130/article/details/135378713
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。