c - 为什么必须在 typedef 中指定此对齐属性?

标签 c attributes memory-alignment struct-member-alignment

我最初是在我的平板电脑上写这个问题的,并且在这样做时采取了很多捷径,所以我认为最终会导致阅读和/或试图回答问题的人感到困惑。

我并不是在寻求解决我最初遇到的问题的方法。如果您真的想了解背景故事,请阅读下一段,否则请跳过。

引起这个问题的是一些旧代码,它对 {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;
}

最佳答案

来自 gcc help files

You may specify the aligned and transparent_union attributes either in a typedef declaration or just past the closing curly brace of a complete enum, struct or union type definition and the packed attribute only past the closing brace of a definition.

所以你可以使用

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

然后用

定义变量
struct Test_t a,b;
struct Test_t *test;

或者你可以使用上面给出的方式。是一样的。

关于c - 为什么必须在 typedef 中指定此对齐属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41180057/

相关文章:

c++ - OpenGL 示例中 WinMain 错误的重新定义

c - 使用 memcpy 连接字符串时打印的奇怪字符

Magento - 在 vi​​ew.phtml 中获取产品项目属性

c - 在 PowerPC 中生成未对齐的内存访问异常

c - 是否保证 C 中的数组元素将连续存储,没有填充?

c - 没有物理内存分配的虚拟内存分配

c++ - 在 macOS 中使用 C/C++ 设置鼠标光标图像

android - 具有任何附加属性的服务属性装饰器会导致 Android 棉花糖出现 "could not parse package"问题

切换到 gradle 后,android 自定义 View 属性不起作用

c++ - 中间指针的动态对齐(16 字节)