1

私はもともとタブレットからこの質問を書き、多くのショートカットを使用したため、最終的に質問を読んだり、質問に答えようとしたりする人々に混乱を招くと思います.

私が最初に抱えていた問題の解決策を求めているわけではありません。裏話が本当に必要な場合は次の段落を読み、それ以外の場合はスキップしてください。

{struct, data, struct, data, ...}これを引き起こしたのは、それぞれdataが任意の長さを持つ形式のデータの配列を操作する古いコードです。コードはポインターを介して各構造体にアクセスし、gcc に切り替えたときに、Solaris でミスアライン アクセスが原因でクラッシュし始めました。これを解決するための 1 つのアイデアは、以下に示すように型のアラインメントを変更することでしたが、私はおそらくそうするつもりはありません。

回答すべき質問は次のように要約できます。

  • ドキュメントには、アラインメントを で減らすことはできないと記載さalignedれていますが、typedef で行うことができます。意図したとおりに機能していますか?
  • 意図したとおりに機能している場合、なぜ typedef が必要なのですか? 構造体定義の一部としてアラインメントを下げることができないのはなぜですか?
    • :それtypedef struct {...}__attribute__((aligned(1))) Typename;も同様に行うことができます

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;
}
4

2 に答える 2

2

gccヘルプ ファイルから

整列属性と transparent_union 属性は、typedef 宣言で指定するか、完全な列挙型、構造体、または共用体型定義の右中括弧の直後に指定できます。packed 属性は、定義の右中括弧の直後にのみ指定できます。

だからあなたが使うことができます

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

次に、変数を次のように定義します

struct Test_t a,b;
struct Test_t *test;

または、上記の方法を使用することもできます。同じです。

于 2016-12-16T08:38:48.580 に答える
1

私は答えを見つけました。私は盲目に違いない。GCC のドキュメントから:

構造体または構造体メンバーで使用する場合、aligned 属性は配置のみを増やすことができます。減らすには、packed 属性も指定する必要があります。typedef の一部として使用された場合、aligned 属性は配置を増減することができ、packed 属性を指定すると警告が生成されます。

于 2016-12-16T17:22:44.343 に答える