2012-06-21 107 views
6

我想C结构的大小是16个字节(16B/32B/48B/..)的倍数。 它的大小并不重要,它只需要16B的倍数。 我该如何强制编译器来做到这一点? 谢谢。C结构大小对齐

+4

什么是编译器? – Joe

+1

您的标题使用单词对齐,但您的问题的正文谈论结构的大小。你究竟想要完成什么?我也很好奇为什么。 –

+0

这里是一个现有的文章,它提供了一个使用联合来填充特定大小的解决方案。然而,该解决方案需要知道结构的大小[结构的大小](http://stackoverflow.com/questions/8705665/force-specific-struct-size-in-c)但是你需要做的是使用字符数组的大小计算,例如(sizeof(struct it)/ 16 + 1)* 16而不是数字常量。 –

回答

5

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编译器的运行时间。

+0

你应该[不要在C](http://stackoverflow.com/a/605858/28169)中投射'malloc()'的返回值。 – unwind

5

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

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

它也可能提供此作为语言扩展。例如,GCC允许你将属性添加到一个定义,其中一个控制对准:

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

对于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。其他编译器也是如此。

+1

对于gcc __attribute__对齐,它实际上是否强制结构大小为16B的倍数?或者它只是保证结构的起始地址与16B对齐? –

+1

结构的起始地址和大小都将对齐到16B。这是为了确保结构阵列元素的正确对齐。 – Romeo

+0

这是不正确的。 __attribute(aligned(x)))宏在x字节边界上分配结构,并且与结构的大小无关http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc /Variable-Attributes.html –

3

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

struct payload_padded a; 

a.p.d = 43.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)]; 
}; 

然后你就可以加衬结构工作,您可以利用这样一个事实,即结构的第一个成员从结构起始处开始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);