Ошибка преобразования указателя с тернарным оператором - PullRequest
20 голосов
/ 25 июля 2011

Я знаю, что у троичного оператора есть некоторые неожиданные ограничения, но я был немного озадачен, что это не скомпилируется для меня:

void foo(bool b)
{
    int* ptr =  ((b) ? NULL : NULL);
}

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

[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'

Компилятор менее чем на 100% соответствует Embarcadero C ++ Builder 2010, поэтому ошибка компилятора вовсе не невозможна ...

ПРИМЕЧАНИЕ:Паренс был изменен, чтобы избежать путаницы с моими намерениями.

ПРИМЕЧАНИЕ2: я немного запутался в том, как я впервые пришел к этой конструкции, поэтому вот мое оправдание: у меня были некоторые ошибки компиляциина линии типа a = b? c : d, где b, c и d были сложными выражениями.Чтобы сузить его, я заменил c и d на NULL s, чтобы проверить, был ли b виновником.В этот момент все пошло к черту в ручной тележке.

Ответы [ 3 ]

23 голосов
/ 25 июля 2011

NULL - это макрос, который расширяется до 0 (или некоторого интегрального константного выражения со значением 0, например, (1 - 1)).В остальном это не «специальный».

Любое выражение с целочисленной константой со значением ноль можно использовать в качестве константы нулевого указателя, что является причиной того, что int* ptr = 0; разрешено.Однако здесь выражение b ? 0 : 0;это не целочисленное константное выражение (b не является константой);его тип - int, который неявно преобразуется в int*

Обходной путь может заключаться в явном указании типа указателя:

int* const null_int_ptr = 0;
int* ptr = b ? null_int_ptr : null_int_ptr;

В примере немногоПридумано, хотя: обычно, когда используется условный оператор, по крайней мере, один из аргументов на самом деле является указателем типа (например, b ? ptr : 0);когда один из операндов является типом указателя, 0 неявно преобразуется в тот же тип указателя, и, следовательно, тип всего условного выражения является типом указателя, а не int.

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

4 голосов
/ 25 июля 2011

Ваша проблема в том, что в вашей системе NULL определено как 0, что предполагается в виде int в контексте троичного оператора. Если вы static_cast один из операндов наберете int*, он должен автоматически преобразовать другой.

Но зачем вообще использовать такую ​​конструкцию?

3 голосов
/ 25 июля 2011

NULL можно определить как имеющий тип int или даже long, поэтому троичный оператор имеет тот же тип. Не существует неявного преобразования в тип указателя, поэтому компилятор генерирует ошибку. Гвоздик здесь заключается в том, что существует неявное преобразование из константного целочисленного выражения, оценивающего в ноль (печально известная константа нулевого указателя).

Возможное решение здесь - явное приведение:

int* ptr =  b ? (int*) NULL : NULL;
...