Подтвердить что ты не робот

VLA и побочный эффект в размере операнда

Я знаю, что sizeof никогда не оценивает свой операнд, кроме как в конкретном случае, когда указанный операнд является VLA. Или, я думал, что знаю.

void g(int n) {
    printf("g(%d)\n", n);
}

int main(void) {
    int i = 12;

    char arr[i]; // VLA

    (void)sizeof *(g(1), &arr); // Prints "g(1)"
    (void)sizeof (g(2), arr);   // Prints nothing

    return 0;
}

Что происходит?

На всякий случай, это скомпилировано с GCC 5.1 на Coliru.

4b9b3361

Ответ 1

Кажется, что я должен дважды подумать перед публикацией, потому что он ударил меня сразу после того, как я это сделал.

Мое понимание того, как sizeof взаимодействует с VLA, действительно корректно, поскольку следующая цитата подтверждает (спасибо @this!):

6.5.3.4 Операторы sizeof и _Alignof
Если тип операнда - тип массива переменной длины, то операнд оценивается; в противном случае операнд не оценивается, а результат представляет собой целочисленную константу

Это не то, что вызывает это удивительное (мне) поведение.

(void)sizeof (g(2), arr);

В подвыражении (g(2), arr), оператор запятой запускает arr распад матрицы на указатель. Таким образом, операнд sizeof больше не является VLA, а простой char*, и он возвращается, чтобы не оценивать его операнд.

Видимо, это поведение было изменено на С++, где оператор запятой больше не будет распадать массивы.