homme.io
Clean.Precise.Quick.
..
SAKURA
PLATO
Фотография
Философия
Искусство
История
DevOps
C/C++
DBMS
Oracle
Спорт
Linux
Rust
Lua
IT

Infinitum.Aeterna
2025.Тайланд
2025.08.Турция
2025.Зубовка
2025.Дивеево
2025.Суздаль-Плес
2025.Рязань
2024.Зубовка
2024.Египет
2024.Эмираты
2024.01.Зоопарк
2024.Китай
Иран в лицах
2023.Иран
2023.09.Египет
2023.07.Царицыно
2023.06.Москва
2023.06.Египет
2023.05.Москва
2023.Стамбул
2023.02.Царицыно
2023.01.Зубовка
2023.ЧИА
2023.ЗИМА
2022.11.Турция
2022.Аносино
2022.ОСЕНЬ
2022.08.Зубовка
2022.07.Турция
2022.Раменское
2022.ЛЕТО
2022.Архангельское
2022.Парк
2022.Петербург
2022.Ярославль
2022.03.Зубовка
2022.Кокошкино
2022.Сочи
2022.ВЕСНА
2022.02.Царицыно
2022.Стамбул
2022.02.Коломенское
2022.ЗИМА
2021.Зубовка
2021.ОСЕНЬ
2021.Египет
2021.Раменское
2021.ЛЕТО
2021.Дивеево
2021.Азов
2021.02.Зоопарк
2021.Карелия
2020.Петербург
2020.Турция
2020.Аносино
2020.Азов
2020.Верея
2020.Арктика
2020.Греция
2019.Турция
2019.Зубовка
2019.Дагестан
2019.Дагестан+
2019.Египет
2019.Италия
2019.Куликово поле
2019.Калуга
2019.02.Танцы
2019.Байкал
2018.Переславль
2018.Плес
2018.Березка
2018.Крым
2018.Азов
2018.Калининград
2018.Петербург
2018.Эльбрус
2017.Турция
2015.Египет
2013.Египет
2013.Рим
Разное

Why we use of do while(0) when we define a macro?

#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

Why do they use this rather than define it simply in a {}?

 

You can follow it with a semicolon and make it look and act more like a function. It also works with if/else clauses properly then.

Without the while(0), your code above would not work with

if (doit) 
   INIT_LIST_HEAD(x);
 else 
   displayError(x);

since the semicolon after the macro would "eat" the else clause, and the above wouldn't even compile.

 

========

Зачем нужна конструкция do { … } while(0)?

/*
 * All of the callbacks setting methods can be generalized to this:
 */
#define SET_CALLBACK(a)                                         \
do                                                              \
{                                                               \
    if( fgStructure.CurrentWindow == NULL )                     \
        return;                                                 \
    SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \
} while( 0 )

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

A:

Конструкция широко используется в "функциональных" макросах и предназначена для объединения нескольких statement и объявлений внутри макроса в один составной statement. Такое объединение нужно для того, чтобы макрос можно было использовать как обычный вызов функции в ветках условного оператора, циклах и т.п. без необходимости постоянно заключать этот вызов во внешнюю пару { ... }

На первый взгляд того же самого можно было бы достичь просто путем заключения самого определения макроса в пару { ... } вместо do { ... } while (0). Однако вариант с { ... } будет обладать одним неприятным недостатком - надо будет постоянно помнить, что его тело представляет из себя { ... }, а после { ... } в С не всегда можно ставить ;. 

Например, если бы тело SET_CALLBACK было заключено просто в { ... }, то вот такой естественно выглядящий код не скомпилировался бы по причине того, что из-за поставленной после SET_CALLBACK(foo) точки с запятой ветка else оказалось оторванной от своего if

if (true)
  SET_CALLBACK(foo); // <- "Лишняя" `;`
else                 // <- Ошибка: оторванный `else`
  /* что-то еще */;

Вот тут-то на сцену и выходит do { ... } while (0). Цикл do/while уникален тем, что является единственной (почти) в языке С грамматической конструкцией, которая формирует блок, и при этом всегда безусловно заканчивается на ;. Благодаря этой замыкающей ; мы можем более естественным образом использовать do { ... } while (0) внутри составных макросов для объединения их в единый statement. В вышеприведенном примере с if ;, указанная после SET_CALLBACK(foo), будет "поглощена" конструкцией do { ... } while (0) и не приведет в "разрушению" целостности if.

Вот именно ради того, чтобы иметь возможность "вызывать" функциональные макросы через тот же естественный синтаксис, через который мы вызываем обычные функции, тело составного макроса и заключают не в { ... }, а именно в do { ... } while (0)

P.S. Почему авторы языка в свое время решили настоять на включении [теоретически совсем не нужной] замыкающей ; в синтаксис do/while - не совсем ясно, но это было сделано.

sdmrnv [2.33ms]