Aqui está o meu código:
#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);
}
Usando o gcc 8.3.0 ou 8.2.1 com qualquer nível de otimização, exceto -O0
, isso gera 0 2
quando eu estava esperando 2 2
. O compilador decidiu que o strlen
limite é b[0]
e, portanto, nunca pode ser igual ou exceder o valor dividido por.
Isso é um erro no meu código ou um erro no compilador?
Isso não está explicitado claramente no padrão, mas eu pensei que a interpretação principal da proveniência do ponteiro era que, para qualquer objeto X
, o código (char *)&X
deve gerar um ponteiro que possa iterar por todo o conjunto X
- esse conceito deve se manter mesmo que X
aconteça sub-matrizes como estrutura interna.
(Pergunta de bônus, existe um sinalizador gcc para desativar essa otimização específica?)
2 2
sob várias opções.
s.b
é limitado a b[0]
8 caracteres e, portanto, duas opções: (1) acesso fora do limite, caso haja 8 caracteres não nulos, que é UB; (2) há um caractere nulo, no qual o len é menor que 8, portanto, dividir por 8 dá zero. Então, colocar juntos (1) + compilador (2) pode usar a UB para dar mesmo resultado para ambos os casos