Как заставить замолчать конкретное предупреждение «бессмысленное сравнение без знака с нулем»? - PullRequest
8 голосов
/ 07 июня 2011

Предположим, у меня есть функция, подобная следующей:

#define LOWER_BOUND 0
#define UPPER_BOUND 42

int is_value_in_range( some_typedef val)
{
    return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND));
}

Если предположить, что предупреждения настроены соответствующим образом, если some_typedef окажется неподписанным типом, я получу предупреждение о бессмысленном сравнении неподписанного типа с 0. Конечно, это правда, и это имеет смысл.

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

  • Хотя границы всегда будут постоянными времени компиляции, они могут быть чем-то, что может измениться (и макросы могут не «жить» очень близко к функции). Например, границы могут быть установлены путем передачи параметров компилятору.
  • Я бы хотел защитить от более позднего изменения typedef на подписанный тип, поскольку вполне возможно, что каждое использование typedef может не подвергаться тщательному анализу при его изменении.

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

То, что зависит от функции, подобной 'STATIC_ASSERT ()' (доступно для меня), будет приемлемым, если это разумно. Я в порядке с нарушением компиляции, если тип меняется, чтобы заставить кого-то взглянуть на код. Но может быть важно отметить, что typeof - это не то, что у меня есть во всех компиляторах, на которые я ориентируюсь.

Я специально ищу решения на языке C, поэтому шаблоны здесь бесполезны ...

Ответы [ 4 ]

6 голосов
/ 07 июня 2011

Если неизвестно, что some_typedef не подписано или не подписано, я думаю, вам не повезло.

Если вы заранее знаете, что some_typedef не подписано, вы можете просто использовать

#if LOWER_BOUND > 0
    return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND));
#else
    return ((val <= UPPER_BOUND));
#endif

Или в этом случае вы можете использовать мою предпочитаемую версию:

    return (val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND);

Редактировать: Я собираюсь предположить, еслиНе известно, что some_typedef имеет особую подпись, тогда UPPER_BOUND и LOWER_BOUND должны быть оба положительными.В противном случае вы получите очень дурацкие результаты, когда some_typedef будет повышен до уровня без знака.Таким образом, вы всегда можете смело использовать:

    return ((uintmax_t)val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND);
2 голосов
/ 07 июня 2011

Это обычно контролируется прагмами. Для MSVC у вас есть #pragma warning, а для GCC у вас есть диагностические прагмы (которые, по общему признанию, не допускают столь детального контроля над предупреждениями, как MSVC, но это все, что у вас есть ).

Оба позволяют механике push / pop изменять только предупреждения для нескольких строк кода.

1 голос
/ 08 июня 2011

Я придумал довольно простое и понятное решение. Копирование нижней границы в переменную приводит к тому, что компилятор перестает жаловаться:

#define LOWER_BOUND 0
#define UPPER_BOUND 42

int is_value_in_range( some_typedef val)
{
    some_typedef lowerbound = LOWER_BOUND;

    return ((lowerbound <= val) && (val <= UPPER_BOUND));
}

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

0 голосов
/ 07 июня 2011

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

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