Ответ 1
Используйте ту же идею, где тип выражения ?:
зависит от того, является ли аргумент константой с нулевым указателем или обычным void *
, но обнаруживает тип с _Generic
:
#define ICE_P(x) _Generic((1? (void *) ((x)*0) : (int *) 0), int*: 1, void*: 0)
Demo on Ideone. _Generic
является добавлением C11, поэтому, если вы застряли на C99 или что-то раньше, вы не будете быть в состоянии использовать его.
Кроме того, у вас есть стандартные ссылки для определение константы нулевого указателя и способ взаимодействия констант нулевого указателя с типом выражения ?:
:
Целочисленное константное выражение со значением 0 или такое выражение, переданное типу void *, называется константой нулевого указателя.
и
Если и второй, и третий операнды являются указателями, а один - константой нулевого указателя, а другой - указателем, тип результата - это указатель на тип, соответствующий всем квалификаторам типов типов, на которые ссылаются оба операнда. Кроме того, если оба операнда являются указателями на совместимые типы или на разные версии совместимых типов, тип результата является указателем на подходящую версию составного типа; , если один операнд является константой нулевого указателя, результат имеет тип другого операнда; в противном случае один операнд является указателем на void или квалифицированной версией void, и в этом случае тип результата является указателем на подходящую версию void.