Неожиданная оптимизация strlen при совмещении 2-го массива - PullRequest
11 голосов
/ 08 ноября 2019

Вот мой код:

#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, чтобы отключить эту конкретную оптимизацию?)

...