В макросах C следует ли делать do {...} while (0,0), а не do {...} while (0)? - PullRequest
16 голосов
/ 06 декабря 2009

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

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

Ответы [ 3 ]

13 голосов
/ 06 декабря 2009

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

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

над

do { ... } while(0)

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

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

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

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

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))

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

12 голосов
/ 29 октября 2014

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

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

РЕДАКТИРОВАТЬ: начиная с Visual Studio 2017 15.3, while(0) больше не генерирует предупреждения (ср. Постоянные условия ). Вы можете избавиться от своего (0,0)!

11 голосов
/ 06 декабря 2009

Хорошо, я пойду за ответом:

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

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

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

...