这是我的代码:
#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
此输出。编译器决定将限制于,因此永远不能等于或超过被除以的值。0 2
2 2
strlen
b[0]
这是我的代码中的错误还是编译器中的错误?
标准中并未明确阐明这一点,但是我认为指针来源的主流解释是,对于任何对象X
,代码(char *)&X
都应生成一个可以迭代整个对象的指针X
-即使X
碰巧具有子数组作为内部结构。
(奖金问题,是否有gcc标志来关闭此特定优化?)
2 2
在各种选项下报告。
s.b
被限制在b[0]
它被限制为8个字符,并因此两个选项:(1)外的束缚的情况下,访问有8个非空字符,这是UB,(2)有一个空字符,其中len小于8,因此除以8得出零。因此,将(1)+(2)编译器放在一起可以使用UB为两种情况提供相同的结果