Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Передача параметров в функцию.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Страницы: 1, 2
Tuma
Добрый день, коллеги!
Возможно я что-то недопонимаю или не знаю в 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.
Mareng
Код
void SendString (char String[])
{
  unsigned int i = 0;
  while (String[i])
    SendChar (String[i++]);
  return;
}
Tuma
Mareng, увы, не помогло.
Упорно присылает только первый символ, а далее - мусор.
Mareng
Цитата(Tuma @ Aug 12 2011, 19:40) *
Самостоятельный вызов SendChar ('a'); работает прекрасно.

А если подряд 5-10 раз вызвать SendChar() с разными аргументами?
zltigo
Ответьте себе на два вопроса:
- Какая архитектура у AVR и как это отражается на процедуре доступа к данным размещенным во Flash и RAM;
- А Ваша функция SendChar() обеспечивает ожидание окончания процесса передачи символа.
Tuma
Цитата
А если подряд 5-10 раз вызвать SendChar() с разными аргументами?

О, что вы! С этого всё начиналось. sm.gif Всё прекрасно работает.

Я заметил что параметр gcc -O - влияет. void SendChar (char _Char) работает всегда.
А вот void SendString (char String[]) показывает первый символ только при -O2 или -O3.
При -O1 и -Os не показывается даже первый символ - только мусор.
При -O2 или -O3 вместо двух символов SendString ("32"); приходит четыре символа: 3???, вместо четырёх - шесть: 3?????.
Замена первого символа влияет, т.е. первый символ приходит корректно.
При попытке послать один символ приходит один корректный символ.
Genadi Zawidowski
Исходники функци передачи символа покажите.
0) не очень хорошая идея свои переменные (имена) начинать с подчёркиваний. Теоретически можно нарваться. В заголовочных файлах такое применяется для того, чтоьы с пользовательскими define не пересечься.

Все приведённые Вами примеры располагают массив символов в ОЗУ.
Формулу зависимости количества мусорных символов от параметра -O выводить не надо. Надо с причиной разбираться. Имейте в виду, что у других всё работает.
zltigo
QUOTE (Genadi Zawidowski @ Aug 12 2011, 18:17) *
Все приведённые Вами примеры располагают массив символов в ОЗУ.

Однако с точностью до наоборот - в приведенных примерах для AVR "массивы символов", ака строки, расположены в ROM. Прикольно?
AHTOXA
Цитата(zltigo @ Aug 12 2011, 22:07) *
Однако с точностью до наоборот - в приведенных примерах для AVR "массивы символов", ака строки, расположены в ROM. Прикольно?

Нет, в winavr строки по умолчанию располагаются в ОЗУ.
zltigo
QUOTE (AHTOXA @ Aug 12 2011, 19:56) *
Нет, в winavr строки по умолчанию располагаются в ОЗУ.

Фу, какой моветон sad.gif. Имеем строчку в ROM для инициализации строчки в RAM. При этом строки в общем-то явно тяготеют к константам. Тогда переходим к ответу на второй вопрос.
_Pasha
Цитата(zltigo @ Aug 12 2011, 20:32) *
Фу, какой моветон sad.gif.

К сожалению, просто const ничего ГЦЦ не говорит про то, что надо в ROM складывать. Но концептуально правильно: указать секцию progmem надо явно, иначе мыж тупые, не знаем, в каком проце как чего... Так что, Вас IAR тоже зомбировал sm.gif, подсадив на удобную фичу. Шучу.
Код
printf_P("1234567890");

Знаменит тем, что форматную строку держит в РОМ адназначна, но при этом putchar() все-таки прописать придется sm.gif
zltigo
QUOTE (_Pasha @ Aug 12 2011, 22:56) *
К сожалению, просто const ничего ГЦЦ не говорит про то, что надо в ROM складывать.

А const тут совсем ни причем - там все чисто все даже по умолчанию вполне разумно во flash класть.
QUOTE
Так что, Вас IAR тоже зомбировал

так к хорошему мгновенно привыкаешь sm.gif
Tuma
Цитата
не очень хорошая идея свои переменные (имена) начинать с подчёркиваний.

Меня ещё мой куратор на первой работе научил так выделять передаваемые в функцию параметры.

Цитата
В заголовочных файлах такое применяется для того, чтоьы с пользовательскими define не пересечься.

Я как-то даже не задумывался что умудрюсь пересечься с какими либо объявлениями. Хотя теоретически это реально.

Всем спасибо, всё переложено в память программы, всё работает.
sergeeff
Цитата(Tuma @ Aug 15 2011, 15:32) *
Меня ещё мой куратор на первой работе научил так выделять передаваемые в функцию параметры.


Очень плохой у вас куратор. Обычно с подчеркивания начинаются служебные зарезервированные имена компилятора, типа __DATE__, __FILE__ , __noop и прочее.
Tuma
Цитата
Обычно с подчеркивания начинаются служебные зарезервированные имена компилятора, типа __DATE__, __FILE__ , __noop и прочее.

Вы же сами написали "__DATE__, __FILE__ , __noop" - всё с двумя подчёркиваниями, а я использую одно и всегда с заглавной буквы - _String, _UARTData и пр..
zltigo
QUOTE (Tuma @ Aug 15 2011, 14:32) *
Меня ещё мой куратор на первой работе научил так выделять передаваемые в функцию параметры.

Уволить без выходного пособие за создание гуано из подчеркиваний, прописных и строчных букв. 100% мерзость.


Tuma
Однако с гарвардской архитектурой у меня пока не очень складывается.
Я научился передавать в функцию константные строки, типа:
Код
SendString (PSTR("Long-long-long String!\n"));

либо через глобальную или локальную статическую переменную:
Код
char TestFlashStr[] PROGMEM = "Test String.\n";
SendString (TestFlashStr);


Разумеется с последующим использованием pgm_read_byte ();.
Но всё это константы.
А как мне передать переменную? Например результат работы функции atoi ();.
_Pasha
Код
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);
zltigo
QUOTE (_Pasha @ Aug 16 2011, 16:50) *
Я бы так делал

Помолчу, но об одном все-же не удержусь спросить - зачем в данном случае узор ввиде do{ .....}while(0); sm.gif
sergeeff
Наверное к тому же, как возврат из функции send_block(char *data, size_t size) указателя на инвалидную ячейку памяти.
Юрий_СВ
Цитата(zltigo @ Aug 16 2011, 19:06) *
Помолчу, но об одном все-же не удержусь спросить - зачем в данном случае узор ввиде do{ .....}while(0); sm.gif

Нормальный общеизвестный приём.
Чтобы ограничить видимость переменной фигурными скобками "липового" while.
_Pasha
Цитата(zltigo @ Aug 16 2011, 19:06) *
зачем в данном случае узор ввиде do{ .....}while(0); sm.gif

Под руку подвернулся способ объявить локальную переменную.

Цитата(sergeeff @ Aug 16 2011, 19:11) *
Наверное к тому же, как возврат из функции send_block(char *data, size_t size) указателя на инвалидную ячейку памяти.

Кому он мешает в данном сферическом случае?
sergeeff
Интересная позиция. Городить do {} while(0) для объявления локальной переменной (видимо для какой-то глубинной оптимизации) - это здорово, а тратить время на запихивание в регистр/ы никчемного указателя - это "не мешающие" мелочи жизни.

А кто мешает без изголизмов:


Код
{
   int result = atoi("6231");
   send_block((char *)&result, sizeof(result));
}
Zlumd
Цитата(Юрий_СВ @ Aug 17 2011, 01:11) *
Нормальный общеизвестный приём.
Чтобы ограничить видимость переменной фигурными скобками "липового" while.
Чтобы ограничить видимость переменной достаточно написать {}. while для этого не требуется.
AHTOXA
Цитата(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;
}

777777
Цитата(Юрий_СВ @ Aug 16 2011, 22:11) *
Нормальный общеизвестный приём.
Чтобы ограничить видимость переменной фигурными скобками "липового" while.

Этот прием используеся для других целей, например чтобы не выполнять последующие условия при выполнении первых:
Код
do
    {
    if(А)
        {
        /* действие для А */
        break;
        }
    if(Б)
        {
        /* действие для Б */
        break;
        }
    if(В)
        {
        /* действие для В */
        break;
        }
    } while (0);

Это придумали goto-ненавистники, они считают что это уродство лучше чем goto.

А чтобы ограничить видимость переменной достаточно просто ограничить ее фигурными скобками. Никто не запрещает ставить их в любом месте программы.
aesok
Цитата(zltigo @ Aug 16 2011, 20:06) *
Помолчу, но об одном все-же не удержусь спросить - зачем в данном случае узор ввиде do{ .....}while(0); sm.gif


ответ тут: http://ru.w3support.net/index.php?db=so&id=1067226

Анатолий.
zltigo
QUOTE (aesok @ Aug 20 2011, 14:02) *

Для особо непонятливых слова "в данном случае" в моем вопросе были выделены жирным шрифтом. Если я выделю их, например, большими красными буквами, Вы сможете дать разумный ответ на вопрос?
aesok
Цитата(zltigo @ Aug 20 2011, 16:10) *
Для особо непонятливых слова "в данном случае" в моем вопросе были выделены жирным шрифтом. Если я выделю их, например, большими красными буквами, Вы сможете дать разумный ответ на вопрос?


Если Ваш вопрос звучит зачем оборачивать в .do{ .....}while(0); (c точкой с запитой), то пусть за свой код отвечает автор. Ссылку я привел для него чтобы он руководствовался знаниями, а не поговоркой "Слышал звон, да не знаю где он.'.

Когда я пишу макрос то хочу чтобы он работал всегда а не только "в данном случае", и поэтому всегда оборачиваю мнотострочный макрос в .do{ .....}while(0) (без точки с запятой).

Анатолий.
_Pasha
Цитата(zltigo @ Aug 20 2011, 15:10) *
Для особо непонятливых слова "в данном случае" в моем вопросе были выделены жирным шрифтом. Если я выделю их, например, большими красными буквами, Вы сможете дать разумный ответ на вопрос?

Повторяю еще раз. Под руку подвернулся способ объявить локальную переменную. А вообще, блоки "от фонаря" лично я не люблю, т.к. для меня они понижают читабельность кода. Думаю, что не я один такой.
zltigo
QUOTE (_Pasha @ Aug 20 2011, 15:27) *
Повторяю еще раз.

Незачем sm.gif. Я и первый раз ответ понял.
QUOTE (aesok @ Aug 20 2011, 15:12) *
Когда я пишу макрос то....

В данном случае это НЕ макрос, а отвечать почему-то Вы начали мне, а не Автору. Что касается обертки всего чего попало макросообразного во while(0), то в ответ на такое вменяемый компилятор встретив бессмысленное выражение будет генерить warning. Посему злоупотреблять, а то употреблять по причине решения притянутой за уши "проблемы", совершенно не следует. Совершенно достаточно заключать многострочные макросы в фигурные скобки. В этом случае либо он будет работать, как положено, либо получите (если вдруг забыли sm.gif, что это FUNCTION() у Вас макрос ) сообщение об ошибке и напишите просто и без затей c фигурными скобками:
if( ... )
{ FUNCTION();
}
else
......

вместо
if( ... )
FUNCTION();
else
......
Юрий_СВ
Цитата(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

zltigo
QUOTE (Юрий_СВ @ Aug 20 2011, 15:53) *
Видимо GCC невменяемый компилятор...

Да sad.gif. Встретив бессмысленную языковую конструкцию он молча без предупреждений ее выкинул. А может программист совершенно другое имел ввиду и банально описался. Есть варианты и похуже - компилятор может и оставить ошметки в коде от таких трюков sad.gif. Аналогично некорректно молча игнорировать, к сожалению, широко бездумно применяемое while( 1 ){.....}
Genadi Zawidowski
Цитата(Tuma @ Aug 15 2011, 16:32) *
Я как-то даже не задумывался что умудрюсь пересечься с какими либо объявлениями. Хотя теоретически это реально.

Не Вы пересечётесь (хотя, можете вполне). Это используется в заголовочных файлах стандартной библиотеки, чтобы не пересечся с Вашими оперделениями, которые не должны начинаться с подчёркивания, например.
zltigo
QUOTE (Genadi Zawidowski @ Aug 20 2011, 17:25) *
чтобы не пересечся с..

Да бог с ними с пересечениями - компилятор выругается в конце концов. Дело в банальном ненужном коверкании и неудобовосприятии. С подчеркивания имеет смысл давать имена тому, что не должно употребляться в явном виде - функции/макросы, которые используются только, например, как, inline в другие и не имеющие самостоятельного смысла. Дефиниции, которые прикрывают от повторного включения заголовочные файлы. Какие-то вещи вызывающие побочные эффекты. Короче, то, что является чем-то запретным/ограниченным для обычного использования в программе и требующее особых причин и внимательности при использовании.
ARV
Цитата(zltigo @ Aug 20 2011, 17:02) *
Да sad.gif . Встретив бессмысленную языковую конструкцию он молча без предупреждений ее выкинул. А может программист совершенно другое имел ввиду и банально описался. Есть варианты и похуже - компилятор может и оставить ошметки в коде от таких трюков sad.gif . Аналогично некорректно молча игнорировать, к сожалению, широко бездумно применяемое while( 1 ){.....}
что-то я не понял сии выпады... поясните, пожалуйста, о чем конкретно вы говорите?
zltigo
QUOTE (ARV @ Aug 20 2011, 19:44) *
что-то я не понял сии выпады... поясните, пожалуйста, о чем конкретно вы говорите?

что-то я не понял сии вопросы... поясните, пожалуйста, о чем конкретно вы спрашиваете?
ARV
Цитата(zltigo @ Aug 20 2011, 21:28) *
что-то я не понял сии вопросы... поясните, пожалуйста, о чем конкретно вы спрашиваете?
что ж...
Цитата
Встретив бессмысленную языковую конструкцию он молча без предупреждений ее выкинул. А может программист совершенно другое имел ввиду и банально описался.
существуют компиляторы, которые угадывают, что хотел программист на основе того, что он написал?

Цитата
Есть варианты и похуже - компилятор может и оставить ошметки в коде от таких трюков.
о чем тут речь? хотелось бы на примере

Цитата
Аналогично некорректно молча игнорировать, к сожалению, широко бездумно применяемое while( 1 ){.....}
а с while(1) что не так?

P.S. вопросы задаю не из потаенного желания уязвить, но из желания узнать правдуновое о GCC, в частности, avr-gcc. век еще не прожил, но учусь все время...

_Pasha
Забыл привести одну конструкцию, используемую в 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)
Это я к чему. Кто нить знает компилятор, который такое "не хавает"?
ARV
Цитата(_Pasha @ Aug 21 2011, 12:02) *
Кто нить знает компилятор, который такое "не хавает"?
и чего тут хорошего?
_Pasha
Цитата(ARV @ Aug 21 2011, 12:44) *
и чего тут хорошего?

Я - не знаю, у меня другая модель этих пресловутых local continuations, свободная от подобных штукесов.
zltigo
QUOTE (ARV @ Aug 21 2011, 10:28) *
существуют компиляторы, которые угадывают, что хотел программист на основе того, что он написал?

Да, практически все sm.gif. Вопрос только в том, генерить или нет компилятору предупреждения, когда он видит бессмысленные с точки зрения генерации кода конструкции, например, все те-же do{...}while(0)
и while( 1 ){...}
Все ведь не все так безобидно с отсутствием предупреждений при выражениях которые верны всегда. Например:
while( value > 1 ){...}
где
#define value 2
Это уже практически наверняка какой-то ляп программиста, о котором надо предупреждать.

QUOTE
о чем тут речь? хотелось бы на примере

Сейчас примера специально искать не буду, и даже, надеюсь, что среди коммерческих компиляторов таких уже нет, но когда компиляторы десяток-другой лет тому назад
были не такими умными, то за примерами ходить далеко не надо было sad.gif.
QUOTE
а с while(1) что не так?

Не так, что используется условие которое верно всегда. Да я понимаю, что это многим уже страшно привычно и не бросается у глаза, и компиляторы давно уже не генерят лишнего кода. Но тем не менее пропускать такое без notes/warning не красиво. А писать такое неграмотно, хотя все поймут, что написавший "ложить" сахар, имел ввиду класть сахар в чай.
ReAl
Цитата(_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.
777777
Цитата(zltigo @ Aug 20 2011, 18:02) *
Аналогично некорректно молча игнорировать, к сожалению, широко бездумно применяемое while( 1 ){.....}


А что это вы против while(1) взъелись? В любой программе для микроконтроллера есть бесконечный цикл. Как вы его кодите? Пишите в конце goto begin?
ReAl
Код
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

sergeeff
Цитата(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)? Ну вроде как основная (теневая) задача крутится. Сиречь нечто, не слишком критичное по времени. Ну и зачем там борьба за возможную лишнюю команду? Возможную, так это дело качества компилятора.
zltigo
QUOTE (sergeeff @ Aug 21 2011, 23:31) *
Ну и зачем....

Я уже писал - как минимум это вопрос просто грамотности.
Кроме того, вечные циклы используются не только в одном единственном случае sm.gif. Задача как правило не одна, и вечные циклы с continue/break тоже совершенно обыденное дело.
777777
Цитата(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)? Ну вроде как основная (теневая) задача крутится. Сиречь нечто, не слишком критичное по времени. Ну и зачем там борьба за возможную лишнюю команду? Возможную, так это дело качества компилятора.

Тем более что эта команда стоит после цикла и никогда не будет выполнена.
ARV
Цитата(zltigo @ Aug 22 2011, 02:03) *
Я уже писал - как минимум это вопрос просто грамотности.


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

с точки зрения здравого смысла оператор for(;;) куда более неграмотное выражение, нежели while(1) - по крайней мере последний здравому смыслу не противоречит.
777777
Цитата(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
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.