C结构大小对齐

问题描述 投票:8回答:4

我希望C结构的大小为16个字节的倍数(16B / 32B / 48B / ..)。达到什么大小都没有关系;它只需要是16个字节的倍数即可。

我如何强制编译器执行此操作?

c struct alignment
4个回答
6
投票

C结构体的大小将取决于该结构体的成员,它们的类型以及它们的数量。确实没有标准方法可以强制编译器将结构设为某个大小的倍数。一些编译器提供了一种编译指示,允许您设置对齐边界,但这确实是另一回事。并且可能有些人会有这样的设置或提供这样的实用性。

但是,如果您坚持使用此方法,则将对结构进行内存分配,并强制将内存分配舍入到下一个16字节大小。

因此,如果您有这样的结构。

struct _simpleStruct {
   int iValueA;
   int iValueB;
};

然后您可以执行以下操作。

{
    struct _simpleStruct *pStruct = 0;
    pStruct = malloc ((sizeof(*pStruct)/16 + 1)*16);
    // use the pStruct for whatever
    free(pStruct);
}

这样做的目的是将大小扩展到您所关心的下一个16字节大小。但是,内存分配器所做的可能是也可能不是给您一个实际上是该大小的块。内存块实际上可能大于您的请求。

例如,如果要对此做一些特殊的事情,比如说要将该结构写入文件,并且想知道块的大小,那么您必须执行与malloc( ),而不是使用sizeof()运算符来计算结构的大小。

所以接下来的事情就是使用诸如此类的宏编写您自己的sizeof()运算符。

#define SIZEOF16(x) ((sizeof(x)/16 + 1) * 16)

据我所知,没有可靠的方法可以从指针中提取已分配块的大小。通常,指针将具有由内存堆管理功能使用的内存分配块,该内存分配块将包含各种内存管理信息,例如分配的块大小,该信息实际上可能大于请求的内存量。但是,此块的格式及其相对于提供的实际内存地址的位置将取决于C编译器的运行时间。


13
投票

对于Microsoft Visual C ++:

#pragma pack(push, 16)

struct _some_struct
{
     ...
}

#pragma pack(pop)

对于GCC:

struct _some_struct { ... } __attribute__ ((aligned (16)));

示例:

#include <stdio.h>

struct test_t {
    int x;
    int y;
} __attribute__((aligned(16)));

int main()
{
    printf("%lu\n", sizeof(struct test_t));
    return 0;
}

gcc -o main main.c编译将输出16。其他编译器也是如此。


5
投票

这完全取决于编译器和其他工具,因为未在ISO C标准中明确指定对齐方式(它指定了对齐可能会在编译器的要求下发生,但未详细说明如何执行)。

您需要查看编译器工具链的特定于实现的内容。它可能提供#pragma pack(或align或其他东西),您可以将其添加到结构定义中。

它也可以将此作为语言扩展提供。例如,gcc允许您向定义中添加属性,其中之一可以控制对齐方式:

struct mystruct { int val[7]; } __attribute__ ((aligned (16)));

3
投票

您也许可以做一个双重结构,将您的实际结构包装在第二个可以添加填充的结构中:

struct payload {
  int a;    /*Your actual fields. */
  float b;
  char c;
  double d;
};

struct payload_padded {
  struct payload p;
  char   padding[16 * ((sizeof (struct payload) + 15) / 16)];
};

然后您可以使用填充的结构:

struct payload_padded a;

a.p.d = 43.3;

当然,您可以利用结构的第一个成员从结构开始处开始的0个字节这一事实,并将指向struct payload_padded的指针视为指向struct payload的指针(因为它是):

float d_plus_2(const struct payload *p)
{
  return p->d + 2;
}

/* ... */

struct payload_padded b;
const double dp2 = d_plus_2((struct payload *) &b);
© www.soinside.com 2019 - 2024. All rights reserved.