|
Гениальное открытие в синтаксисе языка Си, Не стесняемся в овациях :-) |
|
|
|
Sep 28 2009, 11:10
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Sep 28 2009, 13:01)  Код DebugLoop(ShowDebugInfo(); if (I2CMasterState != I2C_SUCCESS)); Код assert(ShowDebugInfo(), I2CMasterState == I2C_SUCCESS);
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 28 2009, 11:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Sep 28 2009, 14:29)  И так допускается использовать assert? Точно так же скомпилится как у меня? Не совсем. Скобки забыл. Код extern void ShowDebugInfo(); int a; void test() { assert((ShowDebugInfo(), a == 2)); }
Errors: none Warnings: none Done. 0 error(s), 0 warning(s)
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 28 2009, 12:01
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Sep 28 2009, 14:56)  Не могли бы Вы выложить дефайн ассерта, который такое "вытворяет". Да любой. Он принимает в качестве параметра выражение, результат которого проверяет на 0. В данном случае я использовал оператор "запятая", объединив в одно выражение и вызов функции и условие, дающее булевый результат. P.S. Пользуясь случаем: спасибо ReAl, который открыл мне этот интересный оператор своими постами.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 28 2009, 14:01
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Сергей Борщ @ Sep 28 2009, 14:10)  Код assert(ShowDebugInfo(), I2CMasterState == I2C_SUCCESS); Ну, и кому такое надо? Процедура ShowDebugInfo() будет вызываться вне зависимости от выполнения условия I2CMasterState == I2C_SUCCESS. Если уж автору исходного топика так хочется что-то (вызов неких действий) добавлять к его исходному действию по условию, то это делается элементарно. Несколько поправил исходный код: Код #define DebugLoop(a) if(a) { DisableIRQ_FIQ(); while (1); } Если мы желаем при выполнении условия ещё и процедуру ShowDebugInfo() вызвать, то следует записать Код DebugLoop( (I2CMasterState != I2C_SUCCESS) ? (ShowDebugInfo(), TRUE) : FALSE ) где FALSE и TRUE соответственно ноль и не ноль. Вот Вам и - пожалуйста: перед заходом в бесконечный цикл получите отладочную информацию. Нечто подобное можно записать и в assert, однако аргумент его используется не только для проверки условия, но и для формирования строки вывода (не смертельно, конечно, но - некрасиво вывод будет смотреться). P.S. В assert , конечно, вызов дополнительной процедуры нужно перенести к FALSE.
|
|
|
|
|
Sep 28 2009, 15:35
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Палыч @ Sep 28 2009, 17:01)  Ну, и кому такое надо? Процедура ShowDebugInfo() будет вызываться вне зависимости от выполнения условия I2CMasterState == I2C_SUCCESS. ... P.S. В assert , конечно, вызов дополнительной процедуры нужно перенести к FALSE. Или так Код assert( I2CMasterState == I2C_SUCCESS || (ShowDebugInfo(), 0) ); DebugLoop( I2CMasterState != I2C_SUCCESS && (ShowDebugInfo(), TRUE) );
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 28 2009, 15:55
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Pasha @ Sep 28 2009, 17:29)  Не-не. Лучше for(){} навернуть функционалом. Чтоб можно было не бояться встретить побочные эффекты от break или return при вызове какого-либо хитрого макроса. Дык вроде break одинаково отрабатывает что из того цикла, что из другого. Это по continue в for хвостовой оператор выполнится. do { } while(0) для другого сделан, чтобы макрос можно было ставить в любое место и привычно писать после него ';', тут уже писали Код // примитив, но для общности изложения #define foo() op1; op2;
if(a) foo(); // в тихую op2 выполняется всегда
if(a) foo(); else // syntax error op3; Код #define foo() { op1; op2; }
if(a) foo(); // "висящий" ';' , но это не страшно
if(a) foo(); else // syntax error op3; Код #define foo() for(int i = 0; i < 1; ++i) { op1; op2; }
if(a) foo(); // "висящий" ';' , но это не страшно
if(a) foo(); else // syntax error op3; Код #define foo() do { op1; op2; } while(0)
if(a) foo(); // OK
if(a) foo(); else // OK op3;
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 28 2009, 16:55
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ReAl @ Sep 28 2009, 18:55)  Дык вроде break одинаково отрабатывает что из того цикла, что из другого. Это по continue в for хвостовой оператор выполнится. Это я про ATOMIC_BLOCK() из winavr - там хвостовая часть с атрибутом cleanup и связана с объявленной локальной переменной, поэтому выполнится всегда, даже при break/return. А так, вообще - про ; подозревал  Ну, и использовать break/continue в других случаях - опять же, создавая макроопределениями единый смысловой контекст - тоже неплохо. Цитата(GetSmart @ Sep 28 2009, 12:51)  Например выполнить какие-нить предворительные действия перед зависанием, которые в режиме Release не будут даже компилироваться, а в Debug будут стоять. Как частный случай этого - оператор if Код #define DEBUGLEVEL 1
#define DEBUG_LOOP(level, assertion) do{if(( level <= DEBUGLEVEL) && (assertion)) for(;;);}while(0) Я правильно понял? level как константное выр-е, так и динамическим может быть. В последнем случае, конечно, надо позаботиться о значении DEBUGLEVEL, чтобы все отфильтровывалось.
|
|
|
|
|
Sep 28 2009, 17:33
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ @ Sep 28 2009, 21:37)  GetSmartу. Его макрос делал то же самое. А в остальном вы все правильно расписали. Ну не знал я про assert. Вот, изобрёл велосипед, а люди вокруг запинали творческую личность  Средневековье какое-то. Знаю, что есть недостаток моего дефайна в том, что он не "ATOMIC", то есть нельзя перед ним написать if (...), хотя условие должно быть внутри (так и было задумано), но иногда из-за этого можно ненароком встать на грабли, если например мой дефайн с процедурой внутри написать сразу после else. Пришлось бы писать примерно так: Код if (...) ++I2CMasterState; else { DebugLoop(ShowDebugInfo(); if (I2CMasterState != I2C_SUCCESS)); }
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|