gpt4 book ai didi

c - 将数组转换为 char* 是否意味着对字符串长度的限制?

转载 作者:太空宇宙 更新时间:2023-11-04 01:47:28 25 4
gpt4 key购买 nike

这段代码应该打印什么?

#include <stdio.h>
#include <string.h>

struct S
{
int x[1];
};

union U
{
struct S arr[64];
char s[256];
};

int main()
{
union U u;
strcpy(u.s, "abcdefghijklmnopqrstuvwxyz");
size_t len = strlen((char*)&u.arr[1].x);
puts(len > 10 ? "YES" : "NO");
return 0;
}

Clang 总是打印“YES”。 GCC 8.1 通过优化打印“NO”,但不发出警告。它是否利用了一些未定义的行为?

最佳答案

是的,gcc 8.1 正在使用未定义的行为。在调用 strlen 时,您对大小为 1 的数组 int 有越界访问。

strlen((char*)&u.arr[1].x);

&u.arr[1].x的类型是int (*)[1]。然后您将其转换为 char*。除非用作 sizeof 的操作数,否则数组的地址与第一个元素的地址具有相同的值。因此在强制转换之前它将具有 &u.arr[1].x[0] 的值,其类型为 int[1]。假设 sizeof(int) == 4,您可以看到读取超过 4 个字节会导致越界访问。

在大小为 1 的数组之后是否有有效内存并不重要。如果您使用小尺寸的基指针派生指针并从中读取,则行为未定义。

您可以通过将数组大小更改为 1、2 和 3 并检查 gcc 生成的程序集来确认 this 是确切原因。

对于 1 和 2,它生成 puts("NO")。但是对于 3,它会生成预期的代码。这是因为您要与 10 进行比较。使用 int[2],长度永远不会大于 10(不调用 UB)。但是 3 的最大字节数是 12。

你可以在这里看到生成的程序集 -

array of size 3对比array of size 2

您可能还想查看 this关于二维数组的类似讨论,我的老问题。

关于c - 将数组转换为 char* 是否意味着对字符串长度的限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50963054/

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