2016-12-16 103 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 –

相關問題