|
|
  |
Передача параметров в функцию., AVR-GCC/ATMega2560 |
|
|
|
Aug 12 2011, 12:40
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Добрый день, коллеги! Возможно я что-то недопонимаю или не знаю в C, посему возник такой вопрос: Код #include <stdio.h> void SendString (const char _String[]) { unsigned int i = 0; while (_String[i] != '\0') { printf ("%c\n", _String[i]); i++; } }
int main (void) { SendString ("LaLa"); return 0; } Прекрасно работает на i386. Но ни одна из Код void SendString (const char _String[]) { unsigned int i = 0; while (_String[i] != '\0') { SendChar (_String[i]); i++; } return; }
void SendString2 (const char *_String) { while (*_String) { SendChar (*_String++); } } ... SendString ("1234567890"); SendString2 ("1234567890"); ... функций не работает - в функцию SendChar передаётся мусор. Самостоятельный вызов SendChar ('a'); работает прекрасно. Как нужно правильно передавать параметры на ATMega/AVR-GCC.
Сообщение отредактировал Tuma - Aug 12 2011, 12:43
|
|
|
|
|
Aug 12 2011, 12:51
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
Код void SendString (char String[]) { unsigned int i = 0; while (String[i]) SendChar (String[i++]); return; }
|
|
|
|
|
Aug 12 2011, 12:58
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Mareng, увы, не помогло. Упорно присылает только первый символ, а далее - мусор.
|
|
|
|
|
Aug 12 2011, 13:03
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487

|
Цитата(Tuma @ Aug 12 2011, 19:40)  Самостоятельный вызов SendChar ('a'); работает прекрасно. А если подряд 5-10 раз вызвать SendChar() с разными аргументами?
|
|
|
|
|
Aug 12 2011, 13:21
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Цитата А если подряд 5-10 раз вызвать SendChar() с разными аргументами? О, что вы! С этого всё начиналось.  Всё прекрасно работает. Я заметил что параметр gcc -O - влияет. void SendChar (char _Char) работает всегда. А вот void SendString (char String[]) показывает первый символ только при -O2 или -O3. При -O1 и -Os не показывается даже первый символ - только мусор. При -O2 или -O3 вместо двух символов SendString ("32"); приходит четыре символа: 3???, вместо четырёх - шесть: 3?????. Замена первого символа влияет, т.е. первый символ приходит корректно. При попытке послать один символ приходит один корректный символ.
|
|
|
|
|
Aug 12 2011, 19:56
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(zltigo @ Aug 12 2011, 20:32)  Фу, какой моветон  . К сожалению, просто const ничего ГЦЦ не говорит про то, что надо в ROM складывать. Но концептуально правильно: указать секцию progmem надо явно, иначе мыж тупые, не знаем, в каком проце как чего... Так что, Вас IAR тоже зомбировал  , подсадив на удобную фичу. Шучу. Код printf_P("1234567890"); Знаменит тем, что форматную строку держит в РОМ адназначна, но при этом putchar() все-таки прописать придется
|
|
|
|
|
Aug 12 2011, 20:47
|

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

|
QUOTE (_Pasha @ Aug 12 2011, 22:56)  К сожалению, просто const ничего ГЦЦ не говорит про то, что надо в ROM складывать. А const тут совсем ни причем - там все чисто все даже по умолчанию вполне разумно во flash класть. QUOTE Так что, Вас IAR тоже зомбировал так к хорошему мгновенно привыкаешь
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 15 2011, 12:32
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Цитата не очень хорошая идея свои переменные (имена) начинать с подчёркиваний. Меня ещё мой куратор на первой работе научил так выделять передаваемые в функцию параметры. Цитата В заголовочных файлах такое применяется для того, чтоьы с пользовательскими define не пересечься. Я как-то даже не задумывался что умудрюсь пересечься с какими либо объявлениями. Хотя теоретически это реально. Всем спасибо, всё переложено в память программы, всё работает.
|
|
|
|
|
Aug 16 2011, 11:32
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Цитата Обычно с подчеркивания начинаются служебные зарезервированные имена компилятора, типа __DATE__, __FILE__ , __noop и прочее. Вы же сами написали " __DATE__, __FILE__ , __noop" - всё с двумя подчёркиваниями, а я использую одно и всегда с заглавной буквы - _String, _UARTData и пр..
|
|
|
|
|
Aug 16 2011, 13:22
|
Группа: Новичок
Сообщений: 6
Регистрация: 12-08-11
Пользователь №: 66 695

|
Однако с гарвардской архитектурой у меня пока не очень складывается. Я научился передавать в функцию константные строки, типа: Код SendString (PSTR("Long-long-long String!\n")); либо через глобальную или локальную статическую переменную: Код char TestFlashStr[] PROGMEM = "Test String.\n"; SendString (TestFlashStr); Разумеется с последующим использованием pgm_read_byte ();. Но всё это константы. А как мне передать переменную? Например результат работы функции atoi ();.
|
|
|
|
|
Aug 16 2011, 14:50
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Код extern void send_char(char what); #define SendStr(s) do{int i; for(i=0;i<sizeof(s);++i) send_char(str[i]);}while(0); #define SendStr_P(s) do{static PROGMEM char str[] = s; int i; for(i=0;i<sizeof(str);++i) send_char(pgm_read_byte(&str[i]));}while(0);
SendStr_P ("Long-long-long String!\n"); Цитата(Tuma @ Aug 16 2011, 16:22)  А как мне передать переменную? Например результат работы функции atoi ();. Я бы так делал Код char * send_block(char *data, size_t size) { while(size--) send_char(*data++); return data; } // пример do { int result = atoi("6231"); send_block((char *)&result, sizeof(result)); } while(0);
Сообщение отредактировал _Pasha - Aug 16 2011, 14:54
|
|
|
|
|
Aug 16 2011, 18:11
|
Участник

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

|
Цитата(zltigo @ Aug 16 2011, 19:06)  Помолчу, но об одном все-же не удержусь спросить - зачем в данном случае узор ввиде do{ .....}while(0);  Нормальный общеизвестный приём. Чтобы ограничить видимость переменной фигурными скобками "липового" while.
|
|
|
|
|
Aug 16 2011, 18:18
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(zltigo @ Aug 16 2011, 19:06)  зачем в данном случае узор ввиде do{ .....}while(0);  Под руку подвернулся способ объявить локальную переменную. Цитата(sergeeff @ Aug 16 2011, 19:11)  Наверное к тому же, как возврат из функции send_block(char *data, size_t size) указателя на инвалидную ячейку памяти. Кому он мешает в данном сферическом случае?
|
|
|
|
|
Aug 16 2011, 19:33
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Интересная позиция. Городить do {} while(0) для объявления локальной переменной (видимо для какой-то глубинной оптимизации) - это здорово, а тратить время на запихивание в регистр/ы никчемного указателя - это "не мешающие" мелочи жизни. А кто мешает без изголизмов: Код { int result = atoi("6231"); send_block((char *)&result, sizeof(result)); }
|
|
|
|
|
Aug 17 2011, 02:49
|
Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 12-04-05
Из: Новосибирск
Пользователь №: 4 057

|
Цитата(Юрий_СВ @ Aug 17 2011, 01:11)  Нормальный общеизвестный приём. Чтобы ограничить видимость переменной фигурными скобками "липового" while. Чтобы ограничить видимость переменной достаточно написать {}. while для этого не требуется.
|
|
|
|
|
Aug 17 2011, 03:11
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(sergeeff @ Aug 16 2011, 22:11)  Наверное к тому же, как возврат из функции send_block(char *data, size_t size) указателя на инвалидную ячейку памяти. Это чем же она "инвалидная"? Нормальная ячейка, первый неотправленный символ. Можно отправлять буфер по частям, типа Код char *ptr = buf_to_send; size_t bytes_to_send = strlen(ptr); while (bytes_to_send) { size_t size = tx_free_size(); if (size > bytes_to_send) size = bytes_to_send; ptr = send_block(ptr, size) bytes_to_send -= size; }
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 17 2011, 09:50
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(Юрий_СВ @ Aug 16 2011, 22:11)  Нормальный общеизвестный приём. Чтобы ограничить видимость переменной фигурными скобками "липового" while. Этот прием используеся для других целей, например чтобы не выполнять последующие условия при выполнении первых: Код do { if(А) { /* действие для А */ break; } if(Б) { /* действие для Б */ break; } if(В) { /* действие для В */ break; } } while (0); Это придумали goto-ненавистники, они считают что это уродство лучше чем goto. А чтобы ограничить видимость переменной достаточно просто ограничить ее фигурными скобками. Никто не запрещает ставить их в любом месте программы.
|
|
|
|
|
Aug 20 2011, 12:02
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(zltigo @ Aug 16 2011, 20:06)  Помолчу, но об одном все-же не удержусь спросить - зачем в данном случае узор ввиде do{ .....}while(0);  ответ тут: http://ru.w3support.net/index.php?db=so&id=1067226Анатолий.
Сообщение отредактировал aesok - Aug 20 2011, 12:03
|
|
|
|
|
Aug 20 2011, 13:12
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(zltigo @ Aug 20 2011, 16:10)  Для особо непонятливых слова "в данном случае" в моем вопросе были выделены жирным шрифтом. Если я выделю их, например, большими красными буквами, Вы сможете дать разумный ответ на вопрос? Если Ваш вопрос звучит зачем оборачивать в .do{ .....}while(0); (c точкой с запитой), то пусть за свой код отвечает автор. Ссылку я привел для него чтобы он руководствовался знаниями, а не поговоркой "Слышал звон, да не знаю где он.'. Когда я пишу макрос то хочу чтобы он работал всегда а не только " в данном случае", и поэтому всегда оборачиваю мнотострочный макрос в .do{ .....}while(0) (без точки с запятой). Анатолий.
|
|
|
|
|
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
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Aug 21 2011, 20:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(ReAl @ Aug 21 2011, 20:04)  Код 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 Для чего обычно пользуем while(1)? Ну вроде как основная (теневая) задача крутится. Сиречь нечто, не слишком критичное по времени. Ну и зачем там борьба за возможную лишнюю команду? Возможную, так это дело качества компилятора.
|
|
|
|
|
Aug 22 2011, 04:25
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(zltigo @ Aug 22 2011, 03:03)  Я уже писал - как минимум это вопрос просто грамотности. Понятно - лично вам такое не нравится. Вообще-то никакие компиляторы давно не выдают предупреждений в подобных случаях. Во-первых, есть системы автоматической генерации кода, например для инициализайии периферии - пользователь ставит флажки в нужных местах, а система генерирует соответствующие #define-ы. Затем они используются в коде примерно таки м образом: Код if (__TIMER_USED & 0x01) { // TIM1 used ... } if (__TIMER_USED & 0x02) { // TIM2 used ... } Те участки, где условие не выполняется, просто выкидываются компилятором. А что было бы если бы на каждый такой случай он выдавал предупреждение? Во-вторых, это актуально при использовании шаблонов - там открывается еще больший простор для оптимизации, компилятор может генерить разный код в зависимости от того является ли параметр шаблона переменной или константой а во втором случае - разный код в зависимости от значения этой константы. Цитата(sergeeff @ Aug 22 2011, 00:31)  Для чего обычно пользуем while(1)? Ну вроде как основная (теневая) задача крутится. Сиречь нечто, не слишком критичное по времени. Ну и зачем там борьба за возможную лишнюю команду? Возможную, так это дело качества компилятора. Тем более что эта команда стоит после цикла и никогда не будет выполнена.
|
|
|
|
|
Aug 22 2011, 05:23
|

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

|
Цитата(zltigo @ Aug 22 2011, 02:03)  Я уже писал - как минимум это вопрос просто грамотности. лично мне кажется, что в данном вопросе while(1) vs for(;;) мы становимся заложниками того, что нам поведал гуру, и тот факт, что гуру мог быть в тот миг пьян, не в духе или просто не придал значения своим словам, даже не приходит нам в голову. я о знаменитых К&R. смотрите сами: while без выражения в скобках (т .е. с пустым местом) не может быть, в то же время в for второй операнд может быть пустым местом, причем, что самое странное, это пустое место воспринимается как истинное логическое выражение. налицо странные противоречия с логикой здравого смысла, возведенные в ранг закона: 1 - это значение логической истины, в то же самое время НИЧЕГО ( пустое место), что мы привыкли отождествлять с НУЛЕМ, вдруг оказывается ИСТИНОЙ в другом операторе... мне кажется, что единожды признав, что А==B, надо впоследствии всегда придерживаться этого, а не менять на противоположное утверждение в зависимости от условий. то есть, сказав, что отсутствие операнда логического отношения приравнивается к ненулевому значению, следовало бы в стандарте допустить while() как пример бесконечного цикла, разрешить if() или switch() без операнда в скобках, а так же признать безошибочной запись а = ? 1 : 0;. а получается, что стандартизировали путаницу в понятиях. с точки зрения здравого смысла оператор for(;;) куда более неграмотное выражение, нежели while(1) - по крайней мере последний здравому смыслу не противоречит.
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 22 2011, 05:59
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(ARV @ Aug 22 2011, 09:23)  лично мне кажется, что в данном вопросе while(1) vs for(;;) мы становимся заложниками того, что нам поведал гуру, и тот факт, что гуру мог быть в тот миг пьян, не в духе или просто не придал значения своим словам, даже не приходит нам в голову. я о знаменитых К&R. смотрите сами: while без выражения в скобках (т .е. с пустым местом) не может быть, в то же время в for второй операнд может быть пустым местом, причем, что самое странное, это пустое место воспринимается как истинное логическое выражение. налицо странные противоречия с логикой здравого смысла Они объясняли это тем, что for(;;) напоминает слово forever - навсегда, намекая на то, что это бесконечный цикл. Таким образом лингвистические соображения взяли верх над логическими. Цитата(ARV @ Aug 22 2011, 09:23)  с точки зрения здравого смысла оператор for(;;) куда более неграмотное выражение, нежели while(1) - по крайней мере последний здравому смыслу не противоречит. +100
|
|
|
|
|
Aug 22 2011, 08:29
|

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

|
QUOTE (777777 @ Aug 22 2011, 07:25)  Вообще-то никакие компиляторы давно не выдают предупреждений в подобных случаях. К счастью, не все комппиляторописатели сдаются перед малограмотной толпой  . Вот, например, IAR: QUOTE D:WORK_ARMXADDMAINmain.c(440) : Remark[Pe236]: controlling expression is constant Отключаемо, как и любые warnings/remarks но таки есть. QUOTE (ARV @ Aug 22 2011, 08:23)  while(1) - по крайней мере последний здравому смыслу не противоречит. Совершенно дикий у Вас "здравый смысл" - написать зачем-то бессмысленное выражение "пока белый цвет белого цвета", после чего ожидать, что компилятором оно будет похерено и получится то, что естественно пишется как for( ; ; ) - выполнять нечто без контроля каких-либо условий. QUOTE (ARV @ Aug 22 2011, 08:23)  в то же время в for второй операнд может быть пустым местом, причем, что самое странное, это пустое место воспринимается как истинное логическое выражение. Воспринимается, как отсутствие каких либо условий для продолжения выполнения цикла. Отсутствие запретов и контроля трактуется, как разрешение. Отсутствие таблички на скамейке в парке об ограничении является естественным указанием на то, что сидеть можно. Табличка на зеленой скамейке - сидеть можно пока скамейка зеленая, просто идиотская.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 22 2011, 08:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(zltigo @ Aug 22 2011, 11:18)  К счастью, не все комппиляторописатели сдаются перед малограмотной толпой  . Что-то вы больно резковаты в выражениях. В конце концов, что такое программа? Инструкции процессору сделать то, что ВЫ от него хотите. Он это делает, хоть 1. while(1) 2. for(;;;) 3. label1: ... goto label1; Какая половая разница? Это напоминает религиозные войны против goto. А что, сколь нибудь значительные по длине циклы while и for в конце концов обходятся без команд переходов на уровне команд процессора?
|
|
|
|
|
Aug 22 2011, 09:15
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(zltigo @ Aug 22 2011, 12:29)  Совершенно дикий у Вас "здравый смысл" - написать зачем-то бессмысленное выражение "пока белый цвет белого цвета" Что ж тут дикого? Аргументом оператора while является логическая переменная, она здесь присутствует и не равна нулю. Цитата(zltigo @ Aug 22 2011, 12:29)  естественно пишется как for( ; ; ) - выполнять нечто без контроля каких-либо условий. А чему равно значение логической переменной при ее отсутствии?  Тут приходится записывать в стандарт костыль, явно утверждающий, что в данной констрокции (и только в ней и никакой больше) отсутствие переменной должно трактоваться как ее истинное значение, а в других случаях как ошибка. Или вы будете спорить с тем, что это костыль? Цитата(zltigo @ Aug 22 2011, 12:29)  Отсутствие таблички на скамейке в парке об ограничении является естественным указанием на то, что сидеть можно. Табличка на зеленой скамейке - сидеть можно пока скамейка зеленая, просто идиотская. Но мы же не о скамейке говорим, а о языке программирования.
|
|
|
|
|
Aug 22 2011, 09:32
|

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

|
QUOTE (777777 @ Aug 22 2011, 12:15)  Что ж тут дикого? Аргументом оператора while является логическая переменная, она здесь присутствует и не равна нулю. скамейке говорим, а о языке программирования. Неправильное, то, что тут присутствует КОНСТАНТА, а не, как Вы сами-же и написали, переменная или выражение. На эту, и вообще все, неправильности компилятору следует реагировать, как на места возможной ошибки программиста, или не полного понимания того, что программист хотел от компилятора.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 22 2011, 10:17
|

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

|
QUOTE (sergeeff @ Aug 22 2011, 13:04)  является допустимым в языке С выражением. Именно по причине того, что это написано в стандарте ("Полные Справочники" я игнорирую  ), я не говорю о том, что компилятор должен генерировать ошибку, только предупреждение о странном выражении в данном контексте. А допустимых, но бессмысленных выражений написать можно массу, навскидку: a = a; b == a; a; (это в случае, если "a" не volatile)
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 22 2011, 12:42
|

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

|
Цитата(zltigo @ Aug 22 2011, 11:29)  Воспринимается, как отсутствие каких либо условий для продолжения выполнения цикла. вот вы сами себя и подловили  : логика - штука железная. итак, провожу разбор вашего же утверждения: отсутствие условий для продолжения означает буквально не надо ничего делать, т.е. цикл должен бы быть не бесконечным, а пустым. ведь в цикле for второй операнд - именно условие ПРОДОЛЖЕНИЯ, а не прекращения цикла. было бы там условие прекращения - тогда ваше утверждение не вступало бы в противоречие со здравым смыслом: нет условий для завершения цикла - значит, цикл вечный.
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 22 2011, 12:53
|

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

|
QUOTE (ARV @ Aug 22 2011, 15:42)  разбор вашего же утверждения: отсутствие условий для продолжения означает буквально не надо ничего делать Отсутствие условий для продолжения означает, что цикл выполняется БЕЗ всяких условий - безусловно. http://www.classes.ru/all-russian/russian-...v-term-2249.htmЯ русский язык, поскольку учился с 6 класса в русской школе, причем очень хорошей русской школе "за бугром", знаю достаточно прилично. Точно так-же я знаю 'C' и не надо пытаться убеждать меня начинать писать на нем безграмотно. Все.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 22 2011, 13:32
|

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

|
Цитата(zltigo @ Aug 22 2011, 15:53)  Отсутствие условий для продолжения означает, что цикл выполняется БЕЗ всяких условий - безусловно. http://www.classes.ru/all-russian/russian-...v-term-2249.htmЯ русский язык, поскольку учился с 6 класса в русской школе, причем очень хорошей русской школе "за бугром", знаю достаточно прилично. Точно так-же я знаю 'C' и не надо пытаться убеждать меня начинать писать на нем безграмотно. Все. я не сомневаюсь, что вы знаете Си на пять с плюсом. я не спорю с тем, что закреплено в стандарте Си. я не спорю с необходимостью соблюдать стандарт. я признаю, что соблюдение правил и есть "грамотность". я лишь пытаюсь заострить ваше внимание на том, что это нелогично. безусловный - не то же самое, что отсутствие условия. пример: условием для продолжения плавания под водой [более 5 минут] является наличие специального дыхательного аппарата. в записи Си это выглядит примерно так: for(; акваланг != 0; ){плаваем}. по-вашему выходит, что отсутсвие всяких условий ( for(;;)) вам позволит плавать под водой как угодно долго, как Ихтиандр?  вы же программист, логика у вас должна сидеть в мозгу лучше, чем даже родной язык! вдумайтесь! и снова: даже если согласиться, что отсутствие условия для продолжения означает БЕЗУСЛОВНОЕ ПРОДОЛЖЕНИЕ, то почему не работает while() - ему надо ОБЯЗАТЕЛЬНО указать условие?! как тут с логикой?
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 22 2011, 14:26
|

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

|
QUOTE (ARV @ Aug 22 2011, 16:32)  то почему не работает while() - ему надо ОБЯЗАТЕЛЬНО указать условие?! как тут с логикой? Например, не стали преумножать способы сделать одно и то-же, сделав такую возможность для for(), как продвинутого варианта while(). Я, пожалуй, ничего против использования и for() без условия не имею, но но в стандарте не требуется. Лично я от отсутствия такой возможности неудобств не испытываю - мне достаточно одного канонического способа однозначного донесения моей мысли компилятору. QUOTE (ARV @ Aug 22 2011, 16:32)  на том, что это нелогично А я уже пытался объяснить Вам, что отсутствие на парковой скамейке таблички, о том, что на ней сидеть можно, равно, как и присутствие такой таблички, означает в конце-концов одно и то-же - сидеть на этой скамейке можно. Только отсутствие таблички с условиями выполнения цикла сидения на скамейке является для меня  много более естественным в нормальной жизни.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 22 2011, 14:34
|

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

|
Цитата(zltigo @ Aug 22 2011, 17:26)  Например, не стали преумножать способы сделать одно и то-же, сделав такую возможность для for(), как продвинутого варианта while(). Я, пожалуй, ничего против использования и for() без условия не имею, но но в стандарте не требуется. Лично я от отсутствия такой возможности неудобств не испытываю - мне достаточно одного канонического способа однозначного донесения моей мысли компилятору.
А я уже пытался объяснить Вам, что отсутствие на парковой скамейке таблички, о том, что на ней сидеть можно, равно, как и присутствие такой таблички, означает одно и то-же - сидеть на этой скамейке можно. Только отсутствие таблички с условиями выполнения цикла сидения на скамейке является много более естественным в нормальной жизни. странно... в одном месте отсутствие операнда приравнивается к ненулевому значению, а в другом - к ошибке... здесь, значит, варианты не поленились множить... как прокомментируете пример с аквалангом? записи while(акваланг != 0) и for(; акваланг !=0; ) читаются и понимаются абсолютно однозначно и логично, но for(;;) ?! теперь о ваших скамейках  представим себе, что в парке вы увидели два вида скамеек: на одних есть надпись СИДЕТЬ МОЖНО, а другие - без оных надписей. это аналоги while(1) и for(;;). в ОБЫЧНОЙ ЖИЗНИ каждый, кто умеет читать, задумается - зачем это на некоторых есть надписи? может, на тех, где нет надписей, СИДЕТЬ НЕЛЬЗЯ?! ведь неспроста же пометили часть скамеек?! вам не кажется, что это логично? я уверен, что даже вы, для которого "отсутсвие таблички много более естественно", перед тем, как сесть на непомеченную скамейку тщательно ее ощупаете - а не покрашена ли она?  в Си есть два цикла (скамейки), позволяющие сделать одно и то же: бесконечно выполняться (сидеть). но для одного нужно явное указание о бесконечности (табличка), для другого - не нужно. где же логика?!
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 22 2011, 18:53
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Думается мне, что все, как часто это бывает в жизни, проще. Отцы-основатели K&R порешили сделать for(;;) бесконечным циклом. Может на первый взгляд все показалось логичным, может еще какие мысли были, только они и знают. А потом может и обнаружилась нелогичность, может нет, не менять же. Так все и осталось.
Я застал по жизни людей, разрабатывавших языки программирования с карандашом в руках. Забавные ассемблеры (по-русски автокоды) с командами СУММ, ВЫВ, ВВ и прочее. Интересные были люди со своим особым стилем мышления. Так что все возможно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|