do {} while (0) зачем?

Oct 07, 2004 6 Replies

Приветствую всех, коллеги!



Задумали сделать одну разаработку на блекфине, с uCLinux на борту. Сам я с Линуксом не сильно знаком (на работе поставил debian на роутер, на нем и тренируюсь), поэтому есть пара вопросов:


1) Кому не лень иногда мылом или аськой отвечать на глупые вопросы про заточке uCLinux под мое железо, сборку инструментов и т.д.?
2) В исходниках Линукса встречается такая конструкция: #define SOME_THING \ do { \ func(arg1,arg2); \ } while (0)

что-то я никак не догоню, зачем функцию "оборачивать" в do {} while?



С уважением, Сергей Борщ


Hello Sergey.

07 Oct 04 10:44, you wrote to all:

SB> 1) Кому не лень иногда мылом или аськой отвечать на глупые вопросы про SB> заточке uCLinux под мое железо, сборку инструментов и т.д.?

Hаверное, лучше здесь, пока не выходит за рамки топика.

SB> 2) В SB> исходниках Линукса встречается такая конструкция: SB> #define SOME_THING \ SB> do { \ SB> func(arg1,arg2); \ SB> } while (0)

SB> что-то я никак не догоню, зачем функцию "оборачивать" в do {} while?

Где-то я встречал объяснение, счас не помню. Что-то связано с использованием макроса в выражениях. Такой макрос всегда выглядит как один оператор. Hе обращай внимания.

Alexey

Привет Sergey!

07 Oct 04 11:44, Sergey A. Borshch писал All:

SB> 1) Кому не лень иногда мылом или аськой отвечать на глупые вопросы про SB> заточке uCLinux под мое железо, сборку инструментов и т.д.?

А можно не мылом? Я тоже как-то хотел его применить, мне было бы интересно послушать. По поводу инструментов типа gcc и binutils могу лишь сказать, что с этим (в отличие от uClinux) никаких проблем у меня никогда не было. Просто делаешь все по инструкции - и все получается.

SB> 2) В SB> исходниках Линукса встречается такая конструкция: #define SB> SOME_THING SB> \ do { \ func(arg1,arg2); \ } while (0)

SB> что-то я никак не догоню, зачем функцию "оборачивать" в do {} while?

Таким образом обычно в языке C оборачивают не функцию, а блок операторов ({}). Дело в том, что после блока операторов в языке C не ставится ";". В результате если ты определишь такой макрос:

#define SMTHNG(x) \ { f1((x) + 5); f2((x) - 10); }

то тебе придется всегда помнить, что SMTHNG() - это не функция, а макрос, и ставить после него ";" не надо, иначе это будет пустой оператор. А вот если этот блок обернуть в do...while(0), то с точки зрения синтаксиса он уже будет неотличим от вызова функции, что гораздо удобнее - не надо забивать себе голову деталями, а потом искать, почему что-то не работает.

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Западно-уральское региональное общество добровольных учредителей.

Алексей, приветствую!

У меня binutils не собрались - внутренняя ошибка в bison. Debian woodo под VMware. Попытка обновить его (bison) из unstable закончилась крахом системы. Восстанавливаю. Как соберу - пойдут более детальные вопросы.

Мне обычно не везет :-)

Понял. Видимо раньше там было несколько вызовов функций, но в процессе доработок осталась одна. Если бы их было больше одной, ответ был бы очевиден. Но решение красивое. Беру на заметку.

С уважением, Сергей Борщ

7-Oct-04 17:08 Sergey A. Borshch wrote to Alex Mogilnikov:

SB> Но решение красивое. Беру на заметку.

Кроме устранения проблем с if( cond) SOME_FUNC; // { }; после разворачивания макроса else { }

это дело небезинтересно в таком виде

... do{ // естественно, коментарий что это не цикл ...

if(error1) break; ... ... ... if(errorN) break; ... }while(0)

вместо ... if(!error1) { ... ... ... if(errorN) { ... } } . . }

чтобы и не выехать очень далеко вправо, и не делать отдельную функцию с if(errorK) return; в тех случаях, когда этой функции пришлось бы передавать по ссылке [почти] все локальные переменные текущей функции.

Но я в таком виде while(0) применял может пару раз, очень уж непривычно для себя самого выглядит. А были бы в С локальные функции, так и вообще это не нужно было бы.

wbr,

Hello, Alex! You wrote to Sergey A. Borshch on Thu, 07 Oct 2004 14:19:48 +0400:

SB>> что-то я никак не догоню, зачем функцию "оборачивать" в do {} SB>> while?

AM> Таким образом обычно в языке C оборачивают не функцию, а блок AM> операторов ({}). Дело в том, что после блока операторов в языке C не AM> ставится ";".

[...] Не только. Таким образом ещё реализуют "блок finally" :-)). Если нужно в нескольких местах прерывать выполнение вложенного блока, то это можно реализовать через goto, через развесистый if, либо через указанную конструкцию: (1) /* */ if (a) goto label; /* */ if (b) goto label; /* */ if (c) goto label; /* */ label: (2) /* */ if (!a) { /* */ if (!b) { /* */ if (!c) { /* */ } } } /* label: */ (3) do { /* */ if (a) break; /* */ if (b) break; /* */ if (c) break; /* */ } while (0); /* label: */

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

Alexander,Derazhne@adic,kiev,ua (replace commas with dots) Alexander Derazhne

Привет Alexander!

08 Oct 04 17:27, Alexander Derazhne писал Alex Mogilnikov:

AD> Hе только. Таким образом ещё реализуют "блок finally" :-)).

А, да. Я так делал пару раз. Hо, конечно, не в виде макроса. :)

AD> Кроме того, такая конструкция предоставляет некоторые удобства при AD> использовании отладчика - если "на метке" стоит return, то пр AD> необходимости можно стать именно на него, а не искать все возвраты. AD> Как по мне - это всё сомнительные преимущества (я имею в виду AD> перечисленные мной).

Хорошее преимущество - я не люблю нагромождения вложенных if(). По break гораздо понятнее куда идти.

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Крыскас. Потому что крыса вам доверяет.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required