2016-12-16 55 views
0

我最初是从我的平板电脑写下这个问题的,并采取了很多快捷方式,因此我认为最终会导致读者和/或试图回答问题的人感到困惑。为什么这个alignment属性必须在typedef中指定?

我不是要求解决我最初开始的问题。如果你真的想要后面的故事阅读下一段,否则跳过它。

带来的是一些旧代码在{struct, data, struct, data, ...}的数据阵列上运行,其中每个data具有任意长度。代码通过指针访问每个结构,当我们切换到gcc时,由于访问错误,它在Solaris中开始崩溃。解决这个问题的一个想法是改变类型的对齐方式,如下所示,但我可能不打算这样做。

要回答的问题可以概括为:

  • 的文档状态对准不能与aligned下降,但我可以用一个typedef来做到这一点。它按预期工作吗?
  • 如果它按预期工作,为什么它需要typedef?为什么我不能降低对齐作为结构定义的一部分?
    • :它可以与typedef struct {...}__attribute__((aligned(1))) Typename;完成以及

这里有一个link to some sample code running on wandbox。在情况下,链接去死:

#include <cstdio> 
#include <assert.h> 

#define ALIGN __attribute__((aligned(1))) 

struct  Misaligned_1_t { int x; double y; float z; }; 
struct ALIGN Misaligned_2_t { int x; double y; float z; }; 
struct  Misaligned_3_t { int x; double y; float z; } ALIGN; 

// The gcc documentation indicates that the "aligned" attribute 
// can only be used to increase alignment, so I was surprised 
// to discover this actually works. Why does it work? 
typedef Misaligned_1_t ALIGN Aligned_t; 

int main(int, char**) { 
    char buffer[256]; 
    // The following is meant to simulate a more complicated scenario: 
    // {SomeStruct, char[arbitrary length], SomeStruct, char[arbitrary length], ...} 
    // ... where accessing, using and changing each SomeStruct will result in 
    // misaligned accesses. 
    auto *m1 = (Misaligned_1_t*)&buffer[1]; 
    auto *m2 = (Misaligned_1_t*)&buffer[1]; 
    auto *m3 = (Misaligned_1_t*)&buffer[1]; 
    auto *a1 = (Aligned_t*)&buffer[1]; 

    // The documentation says we can only reduce alignment with the "packed" attribute, 
    // but that would change the size/layout of the structs. This is to demonstrate 
    // that each type is the same size (and should have the same layout). 
    assert( sizeof(m1) == sizeof(m2) 
     && sizeof(m1) == sizeof(m3) 
     && sizeof(m1) == sizeof(a1)); 

    m1->y = 3.14159265358979323846264; // misaligned access 

    std::printf("%0.16f\n", m2->y); // misaligned access 
    std::printf("%0.16f\n", m3->y); // misaligned access 
    std::printf("%0.16f\n", a1->y); // works fine 

    return 0; 
} 
+0

*“为什么这个alignment属性必须在typedef中指定?”*与什么相反?什么是实际问题? – user694733

+0

为什么不'struct __attribute __((aligned(1)))Test {...}'工作?我阅读文档给我的印象是,如果没有'packed',我不应该降低这种对齐方式,但是因为它似乎工作,我很好奇为什么它不工作没有typedef –

+0

对齐(1)说将结构与1个字节对齐?我不认为这有什么影响。你期望什么效果? – dbrank0

回答

0

我找到了答案。我必须失明。从GCC文档:

在结构或结构成员上使用时,aligned属性只能增加对齐;为了减少它,必须指定packed属性。 当作为typedef的一部分使用时,aligned属性可以增加和减少对齐,并且指定packed属性会生成警告。

2

从GCC help files

您可以指定对齐,无论是在typedef声明或刚刚过去的一个完整的枚举的右花括号transparent_union属性,结构或联合类型定义以及仅在定义的右括号之后的打包属性。

所以,你可以使用

struct Test_t { 
    int x; 
    double y; 
    float z; 
} __attribute__((aligned(1))); 

,然后用

struct Test_t a,b; 
struct Test_t *test; 

定义变量或者你可以使用上面给出的方式。这是相同的。

+0

不幸的是即使在右大括号在我试过的任何编译器中都不起作用。到目前为止只有typedef已经工作 –

+0

它正在我的编译器(cygwin 5.4.0)上工作。但是,属性不是可移植C代码的一部分,所以您应该查看编译器文档以获取有关如何使用它的信息。 –

+0

哪个编译器和版本?我已经尝试了GCC 4.9.2,5.4,6.shinging和clang 3.8 –

相关问题