Является ли использование массива в качестве условного выражения допустимым в C ++? - PullRequest
4 голосов
/ 20 декабря 2011

У меня есть этот код:

int main()
{
    char buffer[10];
    if( buffer ) {
       return 1;
    }
    return 0;
}

, который Visual C ++ 10 интерпретирует следующим образом: buffer распадается на указатель, затем указатель сравнивается с нулем. Когда это компилируется с / O2, проверка исключается, и код становится эквивалентным просто return 1;.

Действителен ли приведенный выше код? Правильно ли компилируется Visual C ++ (я имею в виду затухающую часть, а не оптимизацию)?

Ответы [ 4 ]

7 голосов
/ 20 декабря 2011

C ++ 11, 6.4 / 4:

Значением условия, являющегося выражением, является значение выражения, контекстно преобразованное в bool для операторов, отличных от switch;если это преобразование некорректно, программа некорректно сформирована.

Таким образом, стандарт говорит, что компилятор должен выполнить любые неявные преобразования, имеющиеся в его распоряжении, чтобы преобразовать массив в логическое значение.Распад массива на указатель и преобразование указателя в логическое значение с проверкой на равенство нулю является одним из способов сделать это, так что да, программа хорошо определена, и да, она действительно дает правильный результат - очевидно, так как массивразмещенный в стеке указатель, на который он распадается, никогда не может быть равен нулевому указателю.

Обновление: Что касается , почему следует эта цепочка из двух преобразований:

C ++ 11, 4.2 / 1:

Значение l или значение типа «массив NT» или «массив неизвестной границы T» можно преобразовать в значение типа prvalue.типа «указатель на T».Результатом является указатель на первый элемент массива.

Таким образом, единственное допустимое преобразование из типа массива - это указатель на тип элемента.На первом шаге выбора нет.

C ++ 11, 4.12 / 1:

Значение арифметического перечисления с незаданной областью, указатель , указатель илиуказатель на тип члена может быть преобразован в значение типа bool.Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в false;любое другое значение преобразуется в true.Значение типа std::nullptr_t может быть преобразовано в значение типа bool;результирующее значение равно false.

. Имеется неявное преобразование непосредственно из пустого указателя в логическое значение;поэтому компилятор выбирает это как второй шаг, потому что он позволяет немедленно достичь желаемого результата (преобразование в логическое значение).

3 голосов
/ 20 декабря 2011

Да, преобразование из типа массива в bool четко определяется стандартными преобразованиями. Цитирование C ++ 11, 4/1 (с выделением соответствующих преобразований):

Стандартная последовательность преобразования - это последовательность стандартных преобразований в следующих заказ:

- Ноль или одно преобразование из следующего набора: преобразование lvalue-в-значение, преобразование массива в указатель , и преобразование функции в указатель.

- Ноль или одно преобразование из следующего набора: интегральные рекламные акции, рекламные акции с плавающей запятой, интегральные преобразования, преобразования с плавающей запятой, преобразования с плавающей запятой, преобразования указателя, указатель на преобразования членов и логические преобразования .

- Ноль или одна квалификация.

Стандартная последовательность преобразования будет применена к выражению, если необходимо преобразовать его в требуемое выражение. тип назначения.

1 голос
/ 20 декабря 2011

Да.

if( buffer ) означает: проверьте, не является ли buffer не NULL.Переменная массива указывает на начало массива (если вы не перемещаете его) и эквивалентна указателю.

Оптимизация просто возвращает 1, потому что buffer размещено в стеке, поэтому она определенно имеетзначение (указатель на местоположение в стеке), поэтому оно всегда верно.

0 голосов
/ 20 декабря 2011

Вы сами сказали:

буфер распадается на указатель

Поскольку массив находится в стеке, он не может иметь значение NULL (если что-то идет не так, как разбивка стека).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...