Voici mon code:
#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);
}
Utiliser gcc 8.3.0 ou 8.2.1 avec n'importe quel niveau d'optimisation sauf -O0
, cela sort 0 2
quand je m'y attendais 2 2
. Le compilateur a décidé que le strlen
est limité à b[0]
et ne peut donc jamais égaler ou dépasser la valeur divisée par.
Est-ce un bug dans mon code ou un bug dans le compilateur?
Ce n'est pas clairement énoncé dans la norme, mais je pensais que l'interprétation générale de la provenance du pointeur était que pour tout objet X
, le code (char *)&X
devrait générer un pointeur qui peut itérer sur l'ensemble de X
- ce concept devrait tenir même s'il X
se trouve sous-tableaux comme structure interne.
(Question bonus, existe-t-il un indicateur gcc pour désactiver cette optimisation spécifique?)
2 2
sous diverses options.
s.b
est limité, b[0]
il est limité à 8 caractères, et donc deux options: (1) accès hors limite dans le cas où il y a 8 caractères non nuls, qui est UB, (2) il y a un caractère nul, dans lequel le len est inférieur à 8, donc la division par 8 donne zéro. Ainsi, la compilation du compilateur (1) + (2) peut utiliser l'UB pour donner le même résultat aux deux cas