gpt4 book ai didi

将数组转换为结构体

转载 作者:行者123 更新时间:2023-11-30 19:58:29 27 4
gpt4 key购买 nike

我的好奇心受到以下代码的影响:

struct tree
{
unsigned char apple, leaf;
};

int main(void)
{
void* arr[2] = {(int*)1, (int*)2};
struct tree* myStruct = (struct tree*)arr;

return 1;
}

..逻辑上尝试将数组转换为结构并且不会抛出警告。

这是我将数组转换为结构的方式吗?

最佳答案

Which logically tries to convert array to a structure and throws no warnings.

该代码背后没有任何逻辑。更准确地说,代码无意义尝试将数组转换为结构。然而,C 允许很多废话,当您调用未定义的行为时,一切都可能发生。

这就是幕后发生的事情:

  • void* arr[2] 是一个由两个指针组成的数组,其大小与给定系统的地址总线相同。我们假设地址总线是 32 位。
  • {(int*)1, (int*)2}; 然后采用两个整数文字并将它们各自转换为指针。这在 C 中很好。所以我们有两个 int 指针,地址分别为 0x00000001 和 0x00000002。
  • 然后,int 指针会毫无问题地存储在 void 指针数组中,因为 void 指针和其他类型的指针之间不需要显式转换。
  • 然后(struct tree*)arr将数组疯狂地转换为结构类型。这就打破了所谓的"strict aliasing rule"并且这是未定义的行为。这里你的程序很可能会崩溃并烧毁,因为存在几个潜在的问题。
  • 结构体数据成员的对齐方式不一定与指针变量的对齐方式兼容,并且结构体中可能存在填充字节。 - 此外,没有任何内容表明该结构小于 2 个指针。如果它更大,程序将在读取超出数组末尾时尝试访问越界内存。
  • 此外,给定系统上的 char 表示形式可以是任何内容。它们可能是 8 位,也可能是 16 位,可能带有符号位,也可能不带有符号位。
  • 如果运气好的话,给定机器上的未定义行为可能会像这样:让我们假设字符是 8 位无符号的,并且指针是 32 位的。假设不存在填充或对齐问题。让我们假设当您执行代码时程序不会崩溃并烧毁。在这种情况下,该结构体将采用指针数组中最先遇到的 2 个字节并将它们视为数据。由于该数组包含数据 0x0000000100000002,因此前两个字节是 0x00 和 0x00。 appleleaf 将分别包含值 0 和 0。但这也与字节序相关,指针地址中的哪个字节去哪里取决于您的机器使用小字节序还是大字节序。

Is that the way I convert array to a structure?

不,这是非常糟糕的代码。这没有什么正确的。切勿编写这样的代码。

<小时/>

那么将数组转换为结构体的正确方法是什么?

简单地做:

char arr[2] = {1, 2};
myStruct.apple = arr[1];
myStruct.leaf = arr[2];

这是唯一 100% 防弹的方法。如果您希望使用 memcpy() 或类似的方法来减少手动分配的数量,您必须编写防御性编程来保护自己免受结构填充的影响:

static_assert(sizeof(arr) == sizeof(myStruct), "ERR: struct padding detected");

memcpy(&myStruct, arr, sizeof(myStruct));

关于将数组转换为结构体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26909564/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com