【发布时间】:2020-03-04 16:12:02
【问题描述】:
这是我的代码:
#include <string.h>
#include <stdio.h>
typedef char BUF[8];
typedef struct
{
BUF b[23];
} S;
S s;
int main()
{
int n;
memcpy(&s, "1234567812345678", 17);
n = strlen((char *)&s.b) / sizeof(BUF);
printf("%d\n", n);
n = strlen((char *)&s) / sizeof(BUF);
printf("%d\n", n);
}
将 gcc 8.3.0 或 8.2.1 与除 -O0 之外的任何优化级别一起使用,当我期待 2 2 时,这会输出 0 2。编译器决定strlen 绑定到b[0],因此永远不能等于或超过被除的值。
这是我的代码中的错误还是编译器中的错误?
这在标准中没有明确说明,但我认为指针出处的主流解释是对于任何对象X,代码(char *)&X 应该生成一个可以遍历整个@987654330 的指针@ -- 即使X 恰好有子数组作为内部结构,这个概念也应该成立。
(额外的问题,是否有一个 gcc 标志来关闭这个特定的优化?)
【问题讨论】:
-
参考:我的 gcc 7.4.0 在各种选项下报告
2 2。 -
@Ale 标准保证它们在同一个地址(结构不能有初始填充)
-
@DavidRankin-ReinstateMonica “导致 char (*)[8] 的范围被限制为 b[0]。但据我所知,”我认为这很准确。因为
s.b被限制为b[0],所以它被限制为8 个字符,因此有两个选项:(1)如果有8 个非空字符,即UB,则越界访问,(2)有一个空字符,其中 len 小于 8,因此除以 8 得到零。因此,将 (1)+(2) 编译器放在一起可以使用 UB 对两种情况给出相同的结果 -
is there a gcc flag to turn off this specific optimization?-fno-builtin-strlen似乎可以解决它。
标签: c multidimensional-array compiler-optimization strlen gcc8