Oto mój kod:
#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);
}
Używanie gcc 8.3.0 lub 8.2.1 z dowolnym poziomem optymalizacji, z wyjątkiem -O0
tych wyników, 0 2
gdy się spodziewałem 2 2
. Kompilator zdecydował, że strlen
jest on ograniczony b[0]
i dlatego nigdy nie może być równy ani przekraczać dzielonej wartości.
Czy to błąd w moim kodzie czy błąd w kompilatorze?
Nie jest to wyraźnie określone w standardzie, ale myślałem, że głównym interpretacją pochodzenia wskaźnika jest to, że dla każdego obiektu X
kod (char *)&X
powinien generować wskaźnik, który może się iterować w całym X
- ta koncepcja powinna obowiązywać, nawet jeśli X
zdarzy się, że ma pod-tablice jako struktura wewnętrzna.
(Pytanie dodatkowe, czy istnieje flaga gcc, która wyłącza tę konkretną optymalizację?)
2 2
w różnych opcjach.
s.b
jest ograniczony do b[0]
tego, jest ograniczony do 8 znaków, a zatem dwie opcje: (1) dostęp poza granicami, w przypadku gdy istnieje 8 znaków innych niż null, czyli UB, (2) występuje znak null, w którym długość jest mniejsza niż 8, a zatem podzielenie przez 8 daje zero. Tak więc zestawienie kompilatora (1) + (2) może użyć UB, aby dać ten sam wynik w obu przypadkach