2009-08-14 59 views
0

好的,请允许我重新提出问题,因为没有答案得到我真正感兴趣的内容(道歉,如果像这样的问题的全面编辑是一种人造主义)。用于确定C/C++结构中元素对齐的算法

的几点:

  • 这是一个不同的编译器一个比我测试的离线分析,所以SIZEOF()或类似的将不是我在做什么工作。
  • 我知道它是实现定义的,但我碰巧知道下面我感兴趣的实现。

让我们做一个叫包功能,这需要作为输入一个整数,称为校准和整数的元组,称为元素。它输出另一个整数,称为大小。

功能的工作原理如下:

int pack (int alignment, int[] elements) 
{ 
    total_size = 0; 

    foreach(element in elements) 
    { 
    while(total_size % min(alignment, element) != 0) { ++total_size; } 
    total_size += element; 
    } 

    while(total_size % packing != 0) { ++total_size; } 

    return total_size; 
} 

我想我要问的是“这是什么函数的反函数?”,但我不知道是否反转是正确的term--我不记得曾经用多输入来处理函数的反转,所以我可能只是使用一个不适用的术语。

像我想要的东西(排序)存在;这里我提供了一个函数的伪代码,我们将其称为determine_align。这个函数有点幼稚,因为它只是一次又一次地用不同的输入来调用打包,直到它得到它期望的(或失败的)答案。

int determine_align(int total_size, int[] elements) 
{ 
    for(packing = 1,2,4,...,64) // expected answers. 
    { 
    size_at_cur_packing = pack(packing, elements); 

    if(actual_size == size_at_cur_packing) 
    { 
     return packing; 
    } 
    } 

    return unknown; 
} 

所以问题是,有更好的执行判定_align吗?

谢谢,

回答

3

我让编译器为我做对齐。

在GCC,

typedef struct _foo 
{ 
    u8 v1 __attribute__((aligned(4))); 
    u16 v2 __attribute__((aligned(4))); 
    u32 v3 __attribute__((aligned(8))); 
    u8 v1 __attribute__((aligned(4))); 
} foo; 

编辑:注意的sizeof(富)将返回正确的值,包括任何填充。

Edit2:和offsetof(foo,v2)也适用。给定这两个函数/宏,你可以找出你需要知道的内存中结构布局的一切。

0

您需要垫基础上,下一个字段的位置,然后垫基础上,最大对齐的最后一个元素你在结构中看出。请注意,字段的实际对齐方式是其自然对齐和该结构的打包的最小值。也就是说,如果你有包装,4个字节的结构,双将对齐为4个字节,即使它的自然对齐是8

你可以使内环与total_size+= total_size % min(packing, element.size);你可以更快,如果packing进一步优化它, element.size是两个幂。

7

在C/C++结构成员的对齐是完全实现定义的。这里有几个保证,但我不明白他们会如何帮助你。

因此,没有通用的方法做你想要什么。在特定实现的上下文中,您应该参考涵盖此实现的文档(如果它被覆盖)。

5

当选择怎么收拾成员为struct实现不必须遵循的那种方案,你在你的算法描述,虽然这是一个常见的一种。 (即对齐的最小尺寸的类型和优选的机器对齐尺寸。)

尽管如此,您不必比较struct的整体尺寸以确定已应用于单个struct成员的填充。标准宏offsetof将给出任何单个结构成员的起始struct的字节偏移量。

0

如果问题只是要保证特定的对齐,那很容易。对于特定的排列= 2^N:

void* p = malloc(sizeof(_foo) + alignment -1); 
p = (void*) (((char*)(p) + alignment - 1) & ~alignment); 

我忽略保存到原来的对从malloc返回。如果您打算释放该内存,则需要将该指针保存在某处。

2

我真的不知道你想要做什么,我可能完全误解你在找什么,但如果你想简单地确定一个结构的对齐要求是什么,以下宏可能会有所帮助:

#define ALIGNMENT_OF(t) offsetof(struct { char x; t test; }, test) 

要确定您的foo结构的调整,你可以这样做:

ALIGNMENT_OF(foo); 

如果这不是你最终特林做,有可能这个宏可以帮助你使用任何算法确实想出来。

0

我不确定你想在这里实现什么。正如Pavel Minaev所说,对齐是由编译器处理的,而编译器又受平台的应用程序二进制接口约束,用于数据的访问,这些数据可由不同编译器编译的代码访问。以下论文在需要实现调用约定的编译器上下文中讨论该问题:

Christian Lindig和Norman Ramsey。 堆栈帧的声明组成。在Evelyn Duesterwald,编辑,Proc。第14届国际编译器制造会议,Springer,LNCS 2985,2004。