Цитата(=GM= @ Apr 27 2007, 14:41)

Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-).
Напрасно ерничае - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего

Цитата(=GM= @ Apr 27 2007, 14:41)

Кстати, где бы этого Карнигана&Ричи найти и почитать? Хотелось бы заодно поиметь и текущий стандарт на С, никто не выручит?
Да сколько угодно:
Керниган и Ритчи,
прямая ссылка Стандарт СЦитата(=GM= @ Apr 27 2007, 14:41)

Предположим, что всё так, как вы говорите, зачем тогда ввели 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.
Цитата(=GM= @ Apr 27 2007, 14:41)

Так бы и считали, что 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.
Цитата(=GM= @ Apr 27 2007, 14:41)

То, что конструкция while(!(UCSR0A&(1<<UDRE0))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь.
Напрасно. Поверьте
Цитата(=GM= @ Apr 27 2007, 14:41)

Как знаток С (это без стеба), объясните мне, пожалуйста, такой пример на С, хорошо бы с недвусмысленными пояснениями
Это не С, это С++. С++ я знаю сильно хуже, но попробую:
Код
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 пришлось полистать Страуструпа.
Цитата(=GM= @ Apr 27 2007, 14:41)

И вот эту строчку поясните: 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[i] = t[i]) != '\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++)
;
}
Хотя на первый взгляд то, что мы получили, выглядит загадочно, все же такая запись значительно удобнее, и следует освоить ее, поскольку в Си-программах вы будете с ней часто встречаться.