简体   繁体   English

C 结构大小对齐

[英]C struct size alignment

I want the size of a C struct to be multiple of 16 bytes (16B/32B/48B/..).我希望 C 结构的大小是 16 字节的倍数 (16B/32B/48B/..)。 It does not matter which size it gets to;它的大小无关紧要; it only needs to be multiple of 16 bytes.它只需要是 16 字节的倍数。

How could I enforce the compiler to do that?我怎么能强制编译器这样做呢?

For Microsoft Visual C++:对于 Microsoft Visual C++:

#pragma pack(push, 16)

struct _some_struct
{
     ...
}

#pragma pack(pop)

For GCC:对于海湾合作委员会:

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

Example:例子:

#include <stdio.h>

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

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

compiled with gcc -o main main.c will output 16 .gcc -o main main.c编译会输出16 The same goes for other compilers.其他编译器也是如此。

This depends entirely on the compiler and other tools since alignment is not specified that deeply in the ISO C standard (it specifies that alignment may happen at the compilers behest but does not go into detail as to how to enforce it).这完全取决于编译器和其他工具,因为在 ISO C 标准中并没有详细说明对齐(它指定对齐可能发生在编译器的要求下,但没有详细说明如何强制执行)。

You'll need to look into the implementation-specific stuff for your compiler toolchain.您需要查看编译器工具链的特定于实现的内容。 It may provide a #pragma pack (or align or some other thing) that you can add to your structure defininition.它可能会提供一个#pragma pack (或align或其他东西),您可以将其添加到您的结构定义中。

It may also provide this as a language extension.它还可以将此作为语言扩展提供。 For example, gcc allows you to add attributes to a definition, one of which controls alignment:例如,gcc 允许您向定义添加属性,其中之一控制对齐:

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

The size of a C struct will depend on the members of the struct, their types and how many of them there are. C 结构的大小将取决于结构的成员、它们的类型以及它们的数量。 There is really no standard way to force the compiler to make structs to be a multiple of some size.确实没有标准的方法来强制编译器使结构成为某个大小的倍数。 Some compilers provide a pragma that will allow you to set the alignment boundary however that is really a different thing.一些编译器提供了一个编译指示,允许您设置对齐边界,但这实际上是另一回事。 And there may be some that would have such a setting or provide such a pragma.并且可能会有一些具有这样的设置或提供这样的编译指示。

However if you insist on this one method would be to do memory allocation of the struct and to force the memory allocation to round up to the next 16 byte size.但是,如果您坚持使用这种方法,将对结构进行内存分配并强制内存分配向上舍入到下一个 16 字节大小。

So if you had a struct like this.所以如果你有这样的结构。

struct _simpleStruct {
   int iValueA;
   int iValueB;
};

Then you could do something like the following.然后你可以做类似下面的事情。

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

What this would do is to push the size up to the next 16 byte size so far as you were concerned.就您而言,这样做的目的是将大小推到下一个 16 字节大小。 However what the memory allocator does may or may not be to give you a block that is actually that size.然而,内存分配器所做的可能是也可能不是为您提供一个实际大小的块。 The block of memory may actually be larger than your request.内存块实际上可能比您的请求大。

If you are going to do something special with this, for instance lets say that you are going to write this struct to a file and you want to know the block size then you would have to do the same calculation used in the malloc() rather than using the sizeof() operator to calculate the size of the struct.如果你打算用它做一些特别的事情,例如假设你要将这个结构写入一个文件并且你想知道块大小那么你将不得不做与 malloc() 中使用的相同的计算而不是而不是使用 sizeof() 运算符来计算结构的大小。

So the next thing would be to write your own sizeof() operator using a macro such as.所以接下来就是使用宏来编写自己的 sizeof() 运算符,例如。

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

As far as I know there is no dependable method for pulling the size of an allocated block from a pointer.据我所知,没有可靠的方法可以从指针中提取已分配块的大小。 Normally a pointer will have a memory allocation block that is used by the memory heap management functions that will contain various memory management information such as the allocated block size which may actually be larger than the requested amount of memory.通常,一个指针会有一个内存分配块,由内存堆管理函数使用,其中包含各种内存管理信息,例如分配的块大小,实际上可能大于请求的内存量。 However the format for this block and where it is located relative to the actual memory address provided will depend on the C compiler's run time.然而,该块的格式以及它相对于提供的实际内存地址的位置将取决于 C 编译器的运行时。

You could perhaps do a double struct, wrapping your actual struct in a second one that can add padding:你也许可以做一个双重结构,将你的实际结构包装在第二个可以添加填充的结构中:

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)];
};

Then you can work with the padded struct:然后你可以使用填充结构:

struct payload_padded a;

a.p.d = 43.3;

Of course, you can make use of the fact that the first member of a structure starts 0 bytes from where the structure starts, and treat a pointer to struct payload_padded as if it's a pointer to a struct payload (because it is):当然,您可以利用结构的第一个成员从结构开始处开始 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM