class_addIvar的alignment在Objective-C中是做什么用的?

3

之前有人问过同样的问题:Objective-C Runtime: What to put for size & alignment for class_addIvar? 但是它并没有完全解决。

函数声明如下:

BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types)

用于在Objective-C中创建动态类时添加实例变量。
第四个参数 uint8_t alignment 在苹果文档中有描述: 实例变量的最小对齐字节数为1<<align。实例变量的最小对齐方式取决于ivars类型和机器架构。对于任何指针类型的变量,传递log2(sizeof(pointer_type))。 在一些教程中,只要求如果ivar是指针类型,则应使用 log2(sizeof(pointer_type));如果ivar是值类型,则应使用 sizeof(value_type)。但是为什么?有人能详细解释一下吗?
1个回答

6
如果你真的想学习这些值从哪里来,你需要参考特定架构的ABI参考文档。对于OSX和iOS,它们可以在这里找到:OS XiOS
每个文档都应该有一个名为“数据类型和数据对齐”的部分,用于解释特定架构的这些值。
实际上,自C11以来,您可以使用_Alignof运算符来让编译器为您提供特定类型的正确值(因为它已经需要知道这些信息才能生成适当的机器代码),所以您可以创建一个类似以下内容的class_addIvar
class_addIvar(myClass, "someIvar", sizeof(int), log2(_Alignof(int)), @encode(int))

这将为您处理所有底层类型的细节。

当涉及指针类型时,我认为在class_addIvar中不应该使用_Alignof。在苹果的文档中,应该使用log2(sizeof(pointer_type))。我现在理解了数据对齐的概念,但仍然不理解在class_addIvar中指针类型的对齐方式。 - Zhu Shengqi
@ZhuShengq 抱歉。您应该执行 log2(_Alignof(type))。原因是在 class_addIvar 函数内部,它会通过进行 1 << alignment 操作来调整对齐方式。 - Richard J. Ross III
谢谢,你刚才解决了我的困惑!log2(_Alignof(type))让一切都清晰明了。但是苹果似乎希望我们对于值类型使用_Alignof(int),对于指针类型使用log2(_Alignof(int *))。也许苹果在class_addIvar中进行了值/指针类型检查?我还尝试了一些值类型和指针类型的NSGetSizeAndAlignment实验。有趣的是它们的大小总是等于对齐。也许在其他平台上它不保持这种相等性。 - Zhu Shengqi
@ZhuShengqi 对于任何平台,alignof(type) <= sizeof(type)。因此,如果你有疑问,可以使用log2(sizeof(type)),这总是有效的。在某些平台上,例如,32位整数只能是8位对齐,但这并不意味着它不能也是32位对齐,因为32是8的倍数。 - Richard J. Ross III
@ZhuShengqi 不管它是否是指针类型,你应该始终使用log2(alignof(type))。class_addIvar总是执行1 << alignment。您可以通过查看http://www.opensource.apple.com/source/objc4/objc4-647/runtime/objc-runtime-new.mm中的objc-runtime-new.mm来验证这一点。 - Richard J. Ross III
谢谢!我终于弄清楚这件事了:)感谢您以如此耐心回答我的问题。 - Zhu Shengqi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接