Sizeof ("" + 0)!= sizeof (char *) Ошибка или undefined поведение?

Следующая программа C:

#include <stdio.h>

int main(void)
{
    printf("%u %u %u\n",sizeof "",sizeof(""+0),sizeof(char *));
    return 0;
}

выводит 1 4 4 при компиляции с GCC в Linux, но выводит 1 1 4 при компиляции с Microsoft Visual С++ в Windows. Результат GCC - это то, чего я ожидал бы. Различаются ли они потому, что MSVC имеет ошибку или потому, что sizeof ("" + 0) undefined? Для обоих компиляторов поведение (то есть, будет ли среднее значение напечатано равным первому значению или последнему значению) одинаково независимо от строкового литерала или целочисленной константы, которую вы используете.

Соответствующей ссылкой в ​​стандарте ANSI C, как представляется, является 6.2.2.1 - Lvalues ​​и обозначения функций:

"За исключением случаев, когда он является операндом оператора sizeof... значение lvalue, которое имеет тип" массив типа ", преобразуется в выражение, которое имеет тип" указатель на тип ", который указывает на начальный элемент объекта массива и не является lvalue".

Здесь, хотя "Исключить" не следует применять, потому что в sizeof ("+ 0) литерал array/string является операндом + not sizeof.

Ответы

Ответ 1

Поскольку "fooabc" имеет тип char[7], sizeof("fooabc") дает то же самое, что и sizeof(char[7]). Однако массивы могут быть неявно преобразованы - часть, которую вы указали, - указателям (некоторые ошибочно называют этот "распад" ), и поскольку это необходимо для работы арифметики (+), ""+0 будет иметь тип char*. А указатель char может иметь разный размер, чем массив. В этом отношении поведение MSVC кажется нарушенным.

Ответ 2

Я предполагаю, что это ошибка MSVC.

""+0 берет адрес "" (который затухает в типе char*) и суммирует 0 с ним. Этот тип выражения char*.

Поиграйте немного с этим: какое значение ""+0? и ""+1? и sizeof(""+1)?

Ответ 3

Похож на ошибку в MSVC. По-видимому, оптимизатор удаляет +0, прежде чем делать правильный анализ типов.