|
|
  |
Передача параметров в функцию., AVR-GCC/ATMega2560 |
|
|
|
Aug 20 2011, 13:37
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (_Pasha @ Aug 20 2011, 15:27)  Повторяю еще раз. Незачем  . Я и первый раз ответ понял. QUOTE (aesok @ Aug 20 2011, 15:12)  Когда я пишу макрос то.... В данном случае это НЕ макрос, а отвечать почему-то Вы начали мне, а не Автору. Что касается обертки всего чего попало макросообразного во while(0), то в ответ на такое вменяемый компилятор встретив бессмысленное выражение будет генерить warning. Посему злоупотреблять, а то употреблять по причине решения притянутой за уши "проблемы", совершенно не следует. Совершенно достаточно заключать многострочные макросы в фигурные скобки. В этом случае либо он будет работать, как положено, либо получите (если вдруг забыли  , что это FUNCTION() у Вас макрос ) сообщение об ошибке и напишите просто и без затей c фигурными скобками: if( ... ) { FUNCTION(); } else ...... вместо if( ... ) FUNCTION(); else ......
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 20 2011, 13:53
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 4-05-08
Пользователь №: 37 272

|
Цитата(zltigo @ Aug 20 2011, 16:37)  Что касается обертки всего чего попало макросообразного во while(0), то в ответ на такое вменяемый компилятор встретив бессмысленное выражение будет генерить warning. Видимо GCC невменяемый компилятор... Цитата do { unsigned char i; i=PORTC.IN; 3dc: 80 91 48 06 lds r24, 0x0648 i+=17; 3e0: 8f 5e subi r24, 0xEF ; 239 PORTC.OUT=i; 3e2: e0 e4 ldi r30, 0x40 ; 64 3e4: f6 e0 ldi r31, 0x06 ; 6 3e6: 84 83 std Z+4, r24 ; 0x04 } while(0); Цитата PORTC.OUT=PORTC.IN+17; 3dc: 80 91 48 06 lds r24, 0x0648 3e0: 8f 5e subi r24, 0xEF ; 239 3e2: e0 e4 ldi r30, 0x40 ; 64 3e4: f6 e0 ldi r31, 0x06 ; 6 3e6: 84 83 std Z+4, r24 ; 0x04
|
|
|
|
|
Aug 20 2011, 15:41
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Genadi Zawidowski @ Aug 20 2011, 17:25)  чтобы не пересечся с.. Да бог с ними с пересечениями - компилятор выругается в конце концов. Дело в банальном ненужном коверкании и неудобовосприятии. С подчеркивания имеет смысл давать имена тому, что не должно употребляться в явном виде - функции/макросы, которые используются только, например, как, inline в другие и не имеющие самостоятельного смысла. Дефиниции, которые прикрывают от повторного включения заголовочные файлы. Какие-то вещи вызывающие побочные эффекты. Короче, то, что является чем-то запретным/ограниченным для обычного использования в программе и требующее особых причин и внимательности при использовании.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 21 2011, 08:28
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(zltigo @ Aug 20 2011, 21:28)  что-то я не понял сии вопросы... поясните, пожалуйста, о чем конкретно вы спрашиваете? что ж... Цитата Встретив бессмысленную языковую конструкцию он молча без предупреждений ее выкинул. А может программист совершенно другое имел ввиду и банально описался. существуют компиляторы, которые угадывают, что хотел программист на основе того, что он написал? Цитата Есть варианты и похуже - компилятор может и оставить ошметки в коде от таких трюков. о чем тут речь? хотелось бы на примере Цитата Аналогично некорректно молча игнорировать, к сожалению, широко бездумно применяемое while( 1 ){.....} а с while(1) что не так? P.S. вопросы задаю не из потаенного желания уязвить, но из желания узнать правдуновое о GCC, в частности, avr-gcc. век еще не прожил, но учусь все время...
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 21 2011, 09:02
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Забыл привести одну конструкцию, используемую в Protothreads Итак, макрос Код #define PT_WAIT_UNTIL(pt, condition) \ do { \ LC_SET((pt)->lc); \ if(!(condition)) { \ return PT_WAITING; \ } \ } while(0) , где LC_SET() Код #define LC_SET(s) s = __LINE__; case __LINE__: Поясню для тех, кому не близки Protothreads Общий вариант построения функции с переопределяемой точкой входа - на машине Даффа, имеет упрощенный вид Код unsigned int protothread(unsigned int pc) { switch(pc) { case 0: // отсюда идет инициализация, к делу не относится
//далее, вставим ожидание события PT_WAIT_UNTIL(), получим, разворачивая макрос и немного упрощая концепцию do{ pc = __LINE__; case __LINE__:; if(!condition) return pc; }while(0); } return pc; } И такая чехарда воспринимается компиляторами! Несмотря на то, что по указанному case __LINE__: мы попадем внутрь блока do{}while(0) Это я к чему. Кто нить знает компилятор, который такое "не хавает"?
Сообщение отредактировал _Pasha - Aug 21 2011, 09:05
|
|
|
|
|
Aug 21 2011, 10:21
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ARV @ Aug 21 2011, 10:28)  существуют компиляторы, которые угадывают, что хотел программист на основе того, что он написал? Да, практически все  . Вопрос только в том, генерить или нет компилятору предупреждения, когда он видит бессмысленные с точки зрения генерации кода конструкции, например, все те-же do{...}while(0) и while( 1 ){...} Все ведь не все так безобидно с отсутствием предупреждений при выражениях которые верны всегда. Например: while( value > 1 ){...} где #define value 2 Это уже практически наверняка какой-то ляп программиста, о котором надо предупреждать. QUOTE о чем тут речь? хотелось бы на примере Сейчас примера специально искать не буду, и даже, надеюсь, что среди коммерческих компиляторов таких уже нет, но когда компиляторы десяток-другой лет тому назад были не такими умными, то за примерами ходить далеко не надо было  . QUOTE а с while(1) что не так? Не так, что используется условие которое верно всегда. Да я понимаю, что это многим уже страшно привычно и не бросается у глаза, и компиляторы давно уже не генерят лишнего кода. Но тем не менее пропускать такое без notes/warning не красиво. А писать такое неграмотно, хотя все поймут, что написавший "ложить" сахар, имел ввиду класть сахар в чай.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 21 2011, 11:56
|

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

|
Цитата(_Pasha @ Aug 21 2011, 12:02)  И такая чехарда воспринимается компиляторами! Несмотря на то, что по указанному case __LINE__: мы попадем внутрь блока do{}while(0) Это я к чему. Кто нить знает компилятор, который такое "не хавает"? А разве он после этого будет иметь право называться компилятором языка С ? Дабы не иметь необходимости отвечать «а почему вы спрашиваете?» на «а Вы всегда отвечаете вопросом на вопрос?» : Цитата(C89) 3.6.4 Selection statements Syntax selection-statement: if ( expression ) statement if ( expression ) statement else switch ( expression ) statement
3.6.4.2 The switch statement ... Semantics A switch statement causes control to jump to, into, or past the statement that is the switch body, depending on the value of a controlling expression, and on the presence of a default label and the values of any case labels on or in the switch body. A case or default label is accessible only within the closest enclosing switch statement. После намёка машиной даффа на то, что надо ещё раз прочесть соответствующий раздел стандарта, я это прочёл так: В switch ( expression ) statement нет никаких уточнений по поводу того, что за statement имеется ввиду. Обычно там стоит compound statement. Кстати, в начале compound statement может стоять declaration-list: Код volatile int i;
void moo(int u) { switch (u) { // Это начало обычного compound statement, а не неотъемлемая часть switch volatile int j; case 3: j = u; u = i; i = j + u; break; case 4: j = -u; u = -i; i = j + u; break; } } Главное, чтобы новая переменная инициализировалась в каждой ветке. Или была staticНо никто не мешает поставить туда другой statement, например, цикл... Или... Или обычное, не-составное выражение! Код void foo(int u) { switch (u) case 3: ++i; } Что компилируется, и компилиурется (естественно) в аналогичное Код void foo2(int u) { if (u == 3) ++i; } Конечно, такой switch-powered-if, пришедший из Incredible Machine, никому не нужен. Но хорошо демонстирурует, что statement не обязан быть только compound. Так что switch имеет право ходить везде, где имеет право ходить goto.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Aug 21 2011, 17:04
|

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

|
Код for(;;) { // endless loop } Совсем-совсем формально, возможно, и не отличается от while(1) {} (по стандарту для for(;;) «An omitted expression-2 is replaced by a nonzero constant»), но в качестве примера бесконечного цикла в C99 приведён именно этот вариант. В более ранних книгах тоже. Не помню, чтобы я когда-либо писал while(1) :-) Думаю, это рецидив паскаля :-) Ни в каких компиляторах for(;;) никогда не оставляло хвостов недооптимизации в духе того, что бывало от while(1), например Код jmp cy_end cy_start: ... cy_end: ; типа оптимизировали и пред-проверку поставили в конце, чтобы уменьшить число переходов ; потом увидели, что условие константа и проверку убрали ; но убрать jmp cy_end в начале забыли jmp cy_start
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|