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

Условный оператор с постоянным (истинным) значением?

Я смотрел некоторые макросы препроцессора, используемые в OpenSSL, и я наткнулся на следующее из crypto/stack/safestack.h:

#define CHECKED_STACK_OF(type, p) \
    ((_STACK*) (1 ? p : (STACK_OF(type)*)0))

#define CHECKED_SK_FREE_FUNC(type, p) \
    ((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))

#define CHECKED_SK_FREE_FUNC2(type, p) \
    ((void (*)(void *)) ((1 ? p : (void (*)(type))0)))

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

Какова цель использования 1 выше, поскольку оно всегда верно?

4b9b3361

Ответ 1

Это код, который дважды проверяет, прошел ли правильный тип. Указатель p передается и по типу этого указателя также должен быть вручную введен в макрос.

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

Простой пример:

int* p = NULL ;

1 ? p : ( float* )p ;    //error

1 ? p : ( int* )p ;      //ok

Ответ 2

Это статическое утверждение о типе функции перед броском, обеспечивающее литье под типом.

Из C11 (n1570) 6.5.15 (из раздела ограничений)

Условный оператор

(3) Для второго и третьего операндов будет выполнено одно из следующих действий:

  • [опущен материал без указателя]
  • оба операнда являются указателями на квалифицированные или неквалифицированные версии совместимых типов;
  • один операнд является указателем, а другой - константой нулевого указателя; или
  • один операнд является указателем на тип объекта, а другой - указателем на квалифицированную или неквалифицированную версию void.

Третий операнд - это указатель на функцию (так что последняя пуля никогда не применяется), поэтому она компилируется (без предупреждения), только если либо p является константой нулевого указателя или типа, совместимого с void (*)(type) для последний макрос (после преобразования в указатель функции, если p является обозначением функции).