Denisvak 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Вставлять в обработчик прерывания задержку равно, как и ожидание, обсуждаемое выше - плохой стиль. Лучше, тот же Transmit вызывать в бесконечном цикле по флагу в main_e, а в прерывании этот самый флаг взводить. Задержку я вставлял только для того чтобы увидеть сам импульс на осциле! :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Оператор ! это не побитная инверсия, а логическая. При этом UCSRA&0х10 = true или false. Инверсия этого будет соответственно false или true. Так что запись while(!(UCSRA&(1<<5))) правильна. Насчёт оператора "!" я ошибся, прошу пардону. Но от этого UCSRA&0х10 не станет логической переменной, это двоичное 8-битное число. Да, так можно делать для проверки на 0, но это неправильно, в смысле нелогично. К чему приложим оператор логической инверсии? Я думаю, к логической переменной или выражению. Логичнее было бы сравнивать выработанное число с 0х00 или 0х10, тогда бы появилась логическая переменная. Кстати, как быть, если надо сравнивать несколько бит? По-моему, логичнее так: while(UCSRA&0х6А==0х6А). 0х6А взято от фонаря, как пример. Здесь чётко видно, что для оператора while в скобках проверяется логическая переменная, никаких двусмысленностей. Все подобные дискуссии - от отсутствия знаний. А про отквоченное - так в книжках по С и в стандарте языка четко сказано: в языке С 0 считается false а все, что не 0 считается true. И никаких ограничений на "логическость" аргумента оператора if (и while и т.д.) не накладывается. Это одна из основ языка С. Зная ее, приходишь к пониманию, что while ( !( UCSR0A & (1<<UDRE0)) ) - конструкция абсолютно нормальная и правильная. Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-). Кстати, где бы этого Карнигана&Ричи найти и почитать? Хотелось бы заодно поиметь и текущий стандарт на С, никто не выручит? Предположим, что всё так, как вы говорите, зачем тогда ввели true и false вообще? Так бы и считали, что 0 - это НЕТ, а что ОТЛИЧНО ОТ 0 - это ДА. Ан нет, ввели, и 10 лет не прошло, как ввели. То, что конструкция while(!(UCSR0A&(1<<UDRE0))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь. Как знаток С (это без стеба), объясните мне, пожалуйста, такой пример на С, хорошо бы с недвусмысленными пояснениями int a=0,i=1; bool b=true; cout<<boolalpha; 1) if(b++) a=1; 2) if(i++) a=2; 3) if(b--) a=3; 4) if(i--) a=4; 5) if(i=0.5) a=5; 6) if(i==0.5) a=6; cout<<a,b; Что будет выведено в каждом случае? И вот эту строчку поясните: while(*dest++=*src++); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Насчёт оператора "!" я ошибся, прошу пардону. Но от этого UCSRA&0х10 не станет логической переменной, это двоичное 8-битное число. Да, так можно делать для проверки на 0, но это неправильно, в смысле нелогично. К чему приложим оператор логической инверсии? Я думаю, к логической переменной или выражению.... Здесь действует правило приведения. Если применяется логический оператор (!), то выражение под ним приводится к логическому типу, т. е. если 0 - false, если не 0 - true. Поскольку это свойство является стандартным, то оно врядли претерпит изменение и код будет корректным пока существует язык. Ссылки на Кернигана и Ричи приводились на этом форуме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-).Напрасно ерничае - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего :) Кстати, где бы этого Карнигана&Ричи найти и почитать? Хотелось бы заодно поиметь и текущий стандарт на С, никто не выручит?Да сколько угодно:Керниган и Ритчи, прямая ссылка Стандарт С Предположим, что всё так, как вы говорите, зачем тогда ввели true и false вообще? Будете смеяться, но:Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int. ----------------- 7.16 Booleantype and values<stdbool.h> 2 The macro bool expands to _Bool. 3 The remaining three macros are suitable for use in #if preprocessing directives. They are true which expands to the integer constant 1, false which expands to the integer constant 0 4 Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros bool, true, and false. Как видите, это всего лишь макросы. Реальный тип bool вместе с ключевыми словами true и false введены в С++.Но даже в С++ в логических выражениях bool преобразуется к int, вычисляется результат и результат преобразуется обратно к bool.Так бы и считали, что 0 - это НЕТ, а что ОТЛИЧНО ОТ 0 - это ДА.Да, так и считают.6.3.1.2 Boolean type 1 When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1. То, что конструкция while(!(UCSR0A&(1<<UDRE0))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь.Напрасно. Поверьте ;) Как знаток С (это без стеба), объясните мне, пожалуйста, такой пример на С, хорошо бы с недвусмысленными пояснениямиЭто не С, это С++. С++ я знаю сильно хуже, но попробую:int a=0,i=1; bool b=true; cout<<boolalpha; выходной поток переключается на вывод значений типа bool в виде "true" и "false" 1) if(b++) a=1; А будет равно 1 ибо результатом будет значение b до инкремента(true), b будет преобразован к int (1), выполнен инкремент и результат инкремента (2) будет преобразован к bool (true). 2) if(i++) a=2; a станет равно 2, ибо i было равно 1 и результатом i++ будет 1, i после этого будет равно 2 3) if(b--) a=3; a станет равно 3, b будет преобразован к int (1), выполнен декремент и результат (0) будет преобразован к bool (false). 4) if(i--) a=4; a станет равно четырем, i станет равным 1 5) if(i=0.5) a=5; a останется равным 4, ибо: 0.5 преобразуется к int (преобразование из float делается методом отбрасывания дробной части), т.е. к 0, далее выполняется присвоение i=0, результатом этого присвоениия является 0 (побочным эффектом - то, что i принимает значение 0), аргумент if() приводится к типу bool ( 0=>false ), выражение после if() (a=5) не выполняется (пропускается). 6) if(i==0.5) a=6; i будет преобразован в float, результат сравнениия 0, выражение a=6 пропускается. cout<<a,b; в выходной поток выводятся символы "4false" Кстати, для ответа на 1, 6 пришлось полистать Страуструпа. И вот эту строчку поясните: while(*dest++=*src++);Пожалуй наиболее понятно это объясняют Керниган и Ритчи в главе 5:Дополнительные моменты, связанные с указателями и массивами, проиллюстрируем на несколько видоизмененных вариантах двух полезных программ, взятых нами из стандартной библиотеки. Первая из них, функция strcpy (s, t), копирует строку t в строку s. Хотелось бы написать прямо s = t, но такой оператор копирует указатель, а не символы. Чтобы копировать символы, нам нужно организовать цикл. Первый вариант strcpy, с использованием массива, имеет следующий вид: /* strcpy: копирует t в s; вариант с индексируемым массивом*/ void strcpy(char *s, char *t) { int i; i = 0; while ((s = t) != '\0') i++; } Для сравнения приведем версию strcpy с указателями: /* strcpy: копирует t в s: версия 1 (с указателями) */ void strcpy(char *s, char *t) { while ((*s = *t) != '\0') { s++; t++; } } Поскольку передаются лишь копии значений аргументов, strcpy может свободно пользоваться параметрами s и t как своими локальными переменными. Они должным образом инициализированы указателями, которые продвигаются каждый раз на следующий символ в каждом из массивов до тех пор, пока в копируемой строке t не встретится '\0'. На практике strcpy так не пишут. Опытный программист предпочтет более короткую запись: /* strcpy: копирует t в s; версия 2 (с указателями) */ void strcpy(char *s, char *t) { while ((*s++ = *t++) != '\0') ; } Приращение s и t здесь осуществляется в управляющей части цикла. Значением *t++ является символ, на который указывает переменная t перед тем, как ее значение будет увеличено; постфиксный оператор ++ не изменяет указатель t, пока не будет взят символ, на который он указывает. То же в отношении s: сначала символ запомнится в позиции, на которую указывает старое значение s, и лишь после этого значение переменной s увеличится. Пересылаемый символ является одновременно и значением, которое сравнивается с '\0'. В итоге копируются все символы, включая и заключительный символ '\0'. Заметив, что сравнение с '\0' здесь лишнее (поскольку в Си ненулевое значение выражения в условии трактуется и как его истинность), мы можем сделать еще одно и последнее сокращение текста программы: /* strcpy: копирует t в s; версия 3 (с указателями) */ void strcpy(char *s, char *t) { while (*s++ = *t++) ; } Хотя на первый взгляд то, что мы получили, выглядит загадочно, все же такая запись значительно удобнее, и следует освоить ее, поскольку в Си-программах вы будете с ней часто встречаться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Denisvak 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 (изменено) · Жалоба Кстати, как быть, если надо сравнивать несколько бит? По-моему, логичнее так: while(UCSRA&0х6А==0х6А). 0х6А взято от фонаря, как пример. Думаю можно так while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) )); - тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить. А вот while(UCSRA&0x6A==0x6A); на сколько я понимаю не будет работать. Может конечно и ошибаюсь!!! Изменено 27 апреля, 2007 пользователем Denisvak Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Думаю можно так while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) )); - тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить. Да, работать будет, но вместо ожидаемой проверки двух битов за раз будет два раза считан USCRA и после каждого чтения проверено по одному биту. В некоторых случаях (когда чтение изменяет содержимое читаемого регистра) это недопустимо. Чтобы проверялось два бита, надо писать while ( !( UCSRA & ( (1<<5)|(1<<6) ) )). А вот while(UCSRA&0x6A==0x6A); на сколько я понимаю не будет работать. Может конечно и ошибаюсь!!!Совершенно верно. Ибо это эквивалентно while(UCSRA& (0x6A==0x6A) ) => while(UCSRA & 1), что совсем не похоже на желаемое. (для =GM=: на всякий случай перепроверил себя по книге ;) ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Denisvak 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба В некоторых случаях (когда чтение изменяет содержимое читаемого регистра) это недопустимо. Чтобы проверялось два бита, надо писать while ( !( UCSRA & ( (1<<5)|(1<<6) ) )). Спасибо что поправили. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Думаю можно так while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) )); - тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить. Я верю, боюсь только представить в какой ужасный код превратится сия конструкция после компилятора. Да и разобраться в логике ой как не просто. А если 5 бит? Застрелиться можно. А вот while(UCSRA&0x6A==0x6A); насколько я понимаю, не будет работать. Может конечно и ошибаюсь!!! Нет, это я лопухнулся, вместо "неравно" поставил "равно", вот так надо: while(UCSRA&0x6A!=0x6A); И проверяй хоть 1, хоть 2, хоть 5 бит...конструкция останется той же. Даже для нашего случая будет читабельнее: while(UCSRA&0x10!=0x10); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 27 апреля, 2007 Опубликовано 27 апреля, 2007 · Жалоба Нет, это я лопухнулся, вместо "неравно" поставил "равно", вот так надо: while(UCSRA&0x6A!=0x6A); И проверяй хоть 1, хоть 2, хоть 5 бит...конструкция останется той же.Да не будет она работать: у != и == приоритет выше чем у &. Поэтому сначала будет выполнено 0x6A != 0x6A и даст в результате 0, а потом будет проверяться UCSRA & 0, что всегда дает 0 и компилятор выкинет весь код после if который никогда не должен выполниться и оставит только чтение USCRA, и то только потому, что UCSRA объявлено как volatile. А если бы оно было не volatile - выкинул бы и его чтение. Расставьте правильно скобки и получите то, что вы хотите: while( (UCSRA&0x6A) != 0x6A); При этом осталось разобраться, чего мы хотим: ждать пока не будут выставлены все биты while( (UCSRA&0x6A) != 0x6A); или пока не будет выставлен хотя бы один:while( (UCSRA&0x6A) == 0); <=> while( ! (UCSRA&0x6A) ); или пока выставлен хотя бы один: while( (UCSRA&0x6A) != 0); <=> while(UCSRA&0x6A); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 28 апреля, 2007 Опубликовано 28 апреля, 2007 · Жалоба Напрасно ерничаете - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего :)Не обижайтесь, я смайлик там поставил, хотел пошутить, а вы на полном серьёзе... За ссылки спасибо, кое-что уже скачал, и днём еще Карнигана, спасибо нашему модератору, изучаю, времени только не хватает, как всегда, столько всего интересного кругом... Реальный тип bool вместе с ключевыми словами true и false введены в С++.Но даже в С++ в логических выражениях bool преобразуется к int, вычисляется результат и результат преобразуется обратно к bool. Ужос, зачем нам такой си(:-)? 3) if(b--) a=3; a станет равно 3, b будет преобразован к int (1), выполнен декремент и результат (0) будет преобразован к bool (false). Не так. Уже нарыл в книгах, здесь операция "b--" запрещена, компилятор не пропустит. Ладно, буду изучать дальше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 28 апреля, 2007 Опубликовано 28 апреля, 2007 · Жалоба Я верю, боюсь только представить в какой ужасный код превратится сия конструкция после компилятора.Что-то близкое к Loop: sbis UCSRA, 5 rjmp Loop sbis UCSRA, 6 rjmp Loop Ужос, зачем нам такой си(:-)?-Какой же вы Рыцарь? -Да вот какой уж есть! Шрек1 :laugh: Не так. Уже нарыл в книгах, здесь операция "b--" запрещена, компилятор не пропустит.Интересно, видимо я это пропустил. Процитируйте, если не сложно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 28 апреля, 2007 Опубликовано 28 апреля, 2007 · Жалоба Интересно, видимо я это пропустил. Процитируйте, если не сложно. Use of an Operand of Type bool with the Postfix ++ Operator Applying postfix ++ to a variable of type bool is still allowed for backward compatibility with old code that uses plain int or some typedef, as in bool done = false; while(!done) { if(condition) //...do something else done++; //deprecated } Incrementing a bool always yields true, regardless of the original value. However, this practice is deprecated; therefore, it might not be supported in the future. Remember that applying -- (decrement operator) to a bool variable is illegal. Из книги "ANSI/ISO C++ Professional Programmer's Handbook". Еле эту ссылку нашёл, а вот где оригинальная ссылка, не могу найти(:-( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 28 апреля, 2007 Опубликовано 28 апреля, 2007 · Жалоба Из книги "ANSI/ISO C++ Professional Programmer's Handbook". Еле эту ссылку нашёл, а вот где оригинальная ссылка, не могу найти(:-(Спасибо, записал на корочку. Хотя и не приходилось еще декрементироваить и инкриментировать bool :cranky: :cheers: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться