В макросах C следует ли предпочесть do { … } while(0,0) вместо do { … } while(0)?

StackOverflow https://stackoverflow.com/questions/1853723

Вопрос

Недавно клиент выполнил статический анализ кодовой базы C моего работодателя и предоставил нам результаты.Среди полезных исправлений была просьба изменить известную do { ... } while(0) макрос для do { ... } while(0,0).Я понимаю, что делает их патч (используя оператор последовательности для Возврат вычислите значение второго "0", так что эффект тот же), но не ясно, почему они предпочли бы вторую форму первой форме.

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

Это было полезно?

Решение

Что ж, я пойду за ответом:

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

Нет.Нет никакой законной причины.Оба всегда оцениваются как false, и любой приличный компилятор, вероятно, в любом случае превратит второй в первый в сборке.Если и была какая-то причина, по которой он был недействителен в некоторых случаях, C существует достаточно долго, чтобы эта причина была обнаружена более великими гуру, чем Я.

Если вам нравится, что ваш код строит вам совиные глазки, используйте while(0,0).В противном случае используйте то, что использует остальной мир программирования на C, и скажите инструменту статического анализа вашего клиента, чтобы он его убрал.

Другие советы

Просто предположение о том, почему они могли бы предложить использовать

do { ... } while(0,0)

закончился

do { ... } while(0)

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

Я предполагаю, что инструмент статического анализа жалуется на while цикл управляется константой в более простом случае и не выполняется, когда 0,0 используется.Предложение клиента, вероятно, сделано только для того, чтобы они не получили кучу ложных срабатываний от инструмента.

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

Предложение вашего клиента - это один из обручей, который я использовал, чтобы утихомирить это предупреждение, хотя в моем случае оно не контролировало while цикл, это было сделано для того, чтобы иметь дело с утверждением "всегда терпит неудачу".Иногда у меня будет область кода, которая никогда не должна выполняться (возможно, вариант switch по умолчанию).В этой ситуации у меня могло бы быть утверждение, которое всегда завершается неудачей с каким-либо сообщением:

assert( !"We should have never gotten here, dammit...");

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

assert( ("We should have never gotten here, dammit...", 0));

Предупреждение исчезает, и все счастливы.Я предполагаю, что даже инструмент статического анализа вашего клиента был бы таким же.Обратите внимание, что я обычно скрываю этот фрагмент прыжков с обручем за макросом, например:

#define ASSERT_FAIL( x) assert( ((x), 0))

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

Используя while(0,0) запрещает компилятору Microsoft генерировать предупреждение о состоянии, которое является константой (Предупреждение C4127).

Когда это предупреждение включено (напримерс / W4 или / Wall), его можно отключить в каждом конкретном случае с помощью этого приятного маленького трюка (смотрите эту другую тему).

Редактировать:Начиная с Visual Studio 2017 15.3, while(0) больше не выдает предупреждений (см. Постоянные Условия).Вы можете избавиться от своего (0,0) !

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top