Intereting Posts
Является ли законным использовать memset (, 0,) в массиве удвоений? Почему этот массив имеет все остальные значения, инициализированные до нуля? Поплавок, установленный в 0.1, сравнивает значение false с 0,1 Отладка с VS2013 в программе без оптимизации, но в текущем контексте для локальных переменных нет символа C Ошибка компиляции (нет такого файла или каталога, компиляция завершена) Рекурсивное объявление указателя функции в C Неверный вывод из printf числа Когда-то, когда> было быстрее, чем <… Подождите, что? Функция rand () в C не является случайной даже при посеве не может указывать -o при генерации нескольких выходных файлов Как я могу использовать собственный интерфейс Java для передачи байтового массива в функцию C, которая принимает символ char * в качестве аргумента? Как читать строку UTF-8, учитывая ее длину в символах на простом C89? Разделить строку на целочисленный массив в C C: зачем печатать нулевой символ с печатью% s “(null)”? массивы подстроки указателя

Что делает «делать {…} while (0)» точно в коде ядра?

Возможные дубликаты:
Какая польза от while (0), когда мы определяем макрос?
Почему иногда существуют бессмысленные операторы do / while и if / else в макросах C / C ++?
C многострочный макрос: do / while (0) vs scope block

Я видел много таких обычаев, ранее я, хотя программист хотел легко вырваться из блока кода. Зачем нам нужен цикл {…} while (0)? Мы пытаемся что-то сказать компилятору?

Например, в ядре 2.6.25 Linux, include / asm-ia64 / system.h

/* * - clearing psr.i is implicitly serialized (visible by next insn) * - setting psr.i requires data serialization * - we need a stop-bit before reading PSR because we sometimes * write a floating-point register right before reading the PSR * and that writes to PSR.mfl */ #define __local_irq_save(x) \ do { \ ia64_stop(); \ (x) = ia64_getreg(_IA64_REG_PSR); \ ia64_stop(); \ ia64_rsm(IA64_PSR_I); \ } while (0) 

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

В вашем примере вам нужно написать

 __local_irq_save(1); 

в то время как

 __local_irq_save(1) 

приведет к ошибке об отсутствии точки с запятой. Этого не произойдет, если этого не произойдет. Если бы речь шла только о области обзора, достаточно простой фигурной фигурной скобки.

Он позволяет отображать код здесь:

 if(a) __local_irq_save(x); else ...; // -> if(a) do { .. } while(0); else ...; 

Если они просто использовали { .. } вы получили бы

 if(a) { ... }; else ...; 

Else больше не будет принадлежать никому, потому что точка с запятой будет следующим утверждением и отделяет else от предшествующего if . Ошибка компиляции.

objective do{ ... } while(0) construct состоит в том, чтобы превратить группу операторов в один составной оператор, который может быть прерван с помощью ; , Вы видите, что на языке C конструкция do/while имеет одно странное и необычное свойство: даже если он «работает» как составной оператор, он ожидает ; в конце. Никакие другие составные конструкции в C не обладают этим свойством.

Из-за этого свойства вы можете использовать do/while для написания макросов с несколькими операторами, которые можно безопасно использовать как «обычные» функции, не беспокоясь о том, что находится внутри макроса, как в следующем примере

 if (/* some condition */) __local_irq_save(x); /* <- we can safely put `;` here */ else /* whatever */; 

Ответ уже задан (так что макрос заставляет a ; при вызове), но еще одно использование такого рода операторов, которое я видел: он позволяет переименовать в любом месте «цикла», при необходимости досрочно заканчивая. По сути, «goto», что ваши коллеги-программисты не убили бы вас.

 do { int i = do_something(); if(i == 0) { break; } // Skips the remainder of the logic do_something_else(); } while(0); 

Обратите внимание, что это все еще довольно запутанно, поэтому я не рекомендую его использовать.

Похоже, он там только для обзора. Это похоже на:

 if (true) { // Do stuff. } 

редактировать

Я не вижу его в вашем примере, но вполне возможно, что один из этих вызовов функций на самом деле является макросом, и в этом случае есть одно ключевое различие между do / while (0) и if (true), которое является тем, что первое позволяет continue и break .

Он использует макроактив, как реальный оператор или вызов функции.

Утверждение – это { expression-list } или expression; так что возникает проблема при определении макросов, которым требуется более одного выражения, потому что если вы используете { } тогда синтаксическая ошибка произойдет, если вызывающий макрос достаточно разумно добавит a ; перед другим.

 if(whatever) f(x); else f(y); 

Если f() является одним макросом оператора, отлично, но что, если это макрос и что-то сложное? В итоге вы получите if(...) { s1; s2; }; else ... if(...) { s1; s2; }; else ... if(...) { s1; s2; }; else ... и это не сработает.

Поэтому писатель макроса должен либо превратить его в настоящую функцию, либо обернуть конструкцию в один оператор, либо использовать расширение gnu.

Шаблон do .. while(0) – это подход «обернуть конструкцию».