Ось мій код:
#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) є нульовий символ, в якому лінзи менше 8, отже, ділення на 8 дає нуль. Таким чином, компілятор (1) + (2) може використовувати UB, щоб дати однаковий результат в обох випадках