огласите весь список, пожалуйстаConst14 писал(а):Многие компиляторы
Вопросы по С/С++ (СИ)
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Реклама
Re: Вопросы по С/С++ (СИ)
Чтобы огласить весь список, нужно пересмотреть всё множество компиляторов с языка.
Если Вам не понравилось слово "Многие", то можете заменить его на "Некоторые".
Но, на мой взгляд, сути это не меняет, в общем случае организация цикла do while() и результирующий код для него являются самыми простыми.
Если Вам не понравилось слово "Многие", то можете заменить его на "Некоторые".
Но, на мой взгляд, сути это не меняет, в общем случае организация цикла do while() и результирующий код для него являются самыми простыми.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Ну во всяком случае AVR-GCC 5.2.1 в ваш список не входит...в вышеприведенном тесте проводилась компиляция с оптимизацией -Os, при этом 2 из трех вариантов циклов, делающих одно и то же, заремаривались.
таким образом, на целых 2 байта хуже показал себя цикл while, а остальные два оказались равными.
Код: Выделить всё
#include <avr/io.h>
int main(void){
uint8_t i;
// вариант 1 - 106 байт flash
i = 12;
while(i--){
PORTB = PINC;
}
// вариант 2 - 104 байта flash
for(i = 12; i; i--){
PORTB = PORTC;
}
// вариант 3 - 104 байта flash
i = 12;
do{
PORTB = PORTC;
i--;
} while(i);
}таким образом, на целых 2 байта хуже показал себя цикл while, а остальные два оказались равными.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Не "лучше", а "необходимо" !Const14 писал(а):Но пользоваться лучше тем, который больше подходит для данного конкретного случая
Нужно понимать разницу между
Код: Выделить всё
do{}while();
Код: Выделить всё
while(){}
Код: Выделить всё
for(;;){}
Re: Вопросы по С/С++ (СИ)
ARV
Вы привели частный пример задачи, решаемой с помощью трёх типов цикла, я расписал общий случай.
Естественно, что в результате оптимизации таких простых циклов, генерируемый код имеет одинаковый размер.
Противоречий не вижу. И оспаривать этот пример я, конечно, не буду.
Alex, какой из трёх вариантов, приведённых в примере ARV, Вы считаете "необходимо" использовать?
Спрашиваю потому, что когда писал, то думал, что написать: "следует" или "лучше".
Вы привели частный пример задачи, решаемой с помощью трёх типов цикла, я расписал общий случай.
Естественно, что в результате оптимизации таких простых циклов, генерируемый код имеет одинаковый размер.
Противоречий не вижу. И оспаривать этот пример я, конечно, не буду.
Alex, какой из трёх вариантов, приведённых в примере ARV, Вы считаете "необходимо" использовать?
Спрашиваю потому, что когда писал, то думал, что написать: "следует" или "лучше".
- Реклама
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: Вопросы по С/С++ (СИ)
Отцы основатели (K&R) пишут:
циклы while и for обладают тем приятным свойством, что в них проверка окончания осуществляется в начале, а не в конце цикла. Третий оператор цикла языка C, do-while, проверяет условие окончания в конце, после каждого прохода через тело цикла; тело цикла всегда выполняется по крайней мере один раз.
Как и можно было ожидать, цикл do-while используется значительно реже, чем while и for, составляя примерно пять процентов от всех циклов. Тем не менее, иногда он оказывается полезным, как, например, в следующей функции itoa, которая преобразует число в символьную строку (обратная функции atoi). Эта задача оказывается несколько более сложной, чем может показаться сначала. Дело в том, что простые методы выделения цифр генерируют их в неправильном порядке. Мы предпочли получить строку в обратном порядке, а затем обратить ее.
Код: Выделить всё
/* конвертировать n в строку s */
itoa(n, s)
char s[];
int n;
{
int i, sign;
if((sign = n) < 0) /* сохранить знак */
n = -n; /* сделать n положительным */
i = 0;
do { /* генерируем цифры в обратном порядке */
s[i++] = n % 10 + '0'; /* получить следующую цифру */
} while((n /= 10) > 0); /* удалить ее */
if(sign < 0)
s[i++] = '-'
s[i] = '\0';
reverse(s);
}Цикл do-while здесь необходим, или по крайней мере удобен, поскольку, каково бы ни было значение n, массив s должен содержать хотя бы один символ. Мы заключили в фигурные скобки один оператор, составляющий тело do-while, хотя это и не обязательно, для того, чтобы торопливый читатель не принял часть while за начало оператора цикла while.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
ну приведите аналогичный тест частного случая, подтверждающего ваше утверждение - в чем проблема?Const14 писал(а):вы привели частный пример задачи, решаемой с помощью трёх типов цикла, я расписал общий случай.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Вопросы по С/С++ (СИ)
Собственно, я вообще проблемы не вижу и не могу понять, в чём Вы её видите.
Если мы возьмём пример:
и прокомпилируем "классикой" BC 3.1, то получим:
и увидим, во втором и третьем случае те самые переходы на проверку условия "jmp short @2@86" и "jmp short @3@114"
Теперь прокомпилируем тоже самое компилятором SDCC под "процессор" 8051 и получим код:
Здесь тоже во втором и третьем случае видим дополнительные переходы "jnc 00104$" и "jnc 00105$" с единственным отличием - проверку условия компилятор размещает перед, а не после тела цикла.
Если мы возьмём пример:
Спойлер
Код: Выделить всё
unsigned char a,b,c;
//----------------------
void f1(void)
{
c = 0;
do
{
c += b;
b++;
}while( a>b );
}
void f2(void)
{
c=0;
while( a>b )
{
c += b;
b++;
}
}
void f3(void)
{
for( c=0; a>b; b++ )
{
c += b;
}
}
//----------------------
void main(void)
{
a = 10;
b = 2;
f1();
//---------
a = 10;
b = 2;
f2();
//---------
a = 10;
b = 2;
f3();
}
Спойлер
Код: Выделить всё
;
; void f1(void)
;
assume cs:_TEXT
_f1 proc near
push bp
mov bp,sp
;
; {
; c = 0;
;
mov byte ptr DGROUP:_c,0
@1@58:
;
; do
; {
; c += b;
;
mov al,byte ptr DGROUP:_b
add byte ptr DGROUP:_c,al
;
; b++;
;
inc byte ptr DGROUP:_b
;
; }while( a>b );
;
mov al,byte ptr DGROUP:_a
cmp al,byte ptr DGROUP:_b
ja short @1@58
;
; }
;
pop bp
ret
_f1 endp
;
; void f2(void)
;
assume cs:_TEXT
_f2 proc near
push bp
mov bp,sp
;
; {
; c=0;
;
mov byte ptr DGROUP:_c,0
jmp short @2@86
@2@58:
;
; while( a>b )
; {
; c += b;
;
mov al,byte ptr DGROUP:_b
add byte ptr DGROUP:_c,al
;
; b++;
;
inc byte ptr DGROUP:_b
@2@86:
mov al,byte ptr DGROUP:_a
cmp al,byte ptr DGROUP:_b
ja short @2@58
;
; }
; }
;
pop bp
ret
_f2 endp
;
; void f3(void)
;
assume cs:_TEXT
_f3 proc near
push bp
mov bp,sp
;
; {
; for( c=0; a>b; b++ )
;
mov byte ptr DGROUP:_c,0
jmp short @3@114
@3@58:
;
; {
; c += b;
;
mov al,byte ptr DGROUP:_b
add byte ptr DGROUP:_c,al
inc byte ptr DGROUP:_b
@3@114:
mov al,byte ptr DGROUP:_a
cmp al,byte ptr DGROUP:_b
ja short @3@58
;
; }
; }
;
pop bp
ret
_f3 endp
Теперь прокомпилируем тоже самое компилятором SDCC под "процессор" 8051 и получим код:
Спойлер
Код: Выделить всё
;------------------------------------------------------------
;Allocation info for local variables in function 'f1'
;------------------------------------------------------------
; 8051test.c:6: void f1(void)
; -----------------------------------------
; function f1
; -----------------------------------------
_f1:
ar7 = 0x07
ar6 = 0x06
ar5 = 0x05
ar4 = 0x04
ar3 = 0x03
ar2 = 0x02
ar1 = 0x01
ar0 = 0x00
; 8051test.c:8: c = 0;
mov _c,#0x00
; 8051test.c:9: do
00101$:
; 8051test.c:11: c += b;
mov a,_b
add a,_c
mov _c,a
; 8051test.c:12: b++;
inc _b
; 8051test.c:13: }while( a>b );
clr c
mov a,_b
subb a,_a
jc 00101$
ret
;------------------------------------------------------------
;Allocation info for local variables in function 'f2'
;------------------------------------------------------------
; 8051test.c:16: void f2(void)
; -----------------------------------------
; function f2
; -----------------------------------------
_f2:
; 8051test.c:18: c=0;
mov _c,#0x00
; 8051test.c:19: while( a>b )
00101$:
clr c
mov a,_b
subb a,_a
jnc 00104$
; 8051test.c:21: c += b;
mov a,_b
add a,_c
mov _c,a
; 8051test.c:22: b++;
inc _b
sjmp 00101$
00104$:
ret
;------------------------------------------------------------
;Allocation info for local variables in function 'f3'
;------------------------------------------------------------
; 8051test.c:26: void f3(void)
; -----------------------------------------
; function f3
; -----------------------------------------
_f3:
; 8051test.c:28: for( c=0; a>b; b++ )
mov _c,#0x00
00103$:
clr c
mov a,_b
subb a,_a
jnc 00105$
; 8051test.c:30: c += b;
mov a,_b
add a,_c
mov _c,a
; 8051test.c:28: for( c=0; a>b; b++ )
inc _b
sjmp 00103$
00105$:
ret
Последний раз редактировалось Const14 Пт окт 27, 2017 15:17:15, всего редактировалось 1 раз.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
аналогичноConst14 писал(а):я вообще проблемы не вижу и не могу понять, в чём Вы её видите
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Немножко странный код в том смысле, что коль скоро глобальная переменная b изменяется в каждой функции, так что на входы второй и третьей приходят уже разные данные.
Да и первая функция считает чуть по-другому, чем вторая и третья
Да и первая функция считает чуть по-другому, чем вторая и третья
Re: Вопросы по С/С++ (СИ)
Код не имеет какого-либо практичского назначения, не ищите в нём смысл, вызовы функций f1, f2, f3 формальны. Немного поправил, чтобы уж совсем странно не выглядело.
Первая функция иллюстрирует цикл do ... while() и генерируемый для него код. Ещё раз повторю, что использовать его можно только в том случае, если тело цикла должно выполниться хотя-бы один раз!
Первая функция иллюстрирует цикл do ... while() и генерируемый для него код. Ещё раз повторю, что использовать его можно только в том случае, если тело цикла должно выполниться хотя-бы один раз!
Re: Вопросы по С/С++ (СИ)
Дык я об этом и сказал: do..while всегда быстрее или такой же как и while(). В простых циклах, когда компилятору удаётся превратить while() в do {} while, то разницы не будет.на целых 2 байта хуже показал себя цикл while
Если подумать головой и посмотреть на код, то должно стать понятно и так, что while() медленнее.
да-да-да. А потом удивляемся кто же пишет всё гавённое тормозящее ПО.весь сыр-бор из-за жалкого jmp, которого иногда может и не быть
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Вопросы по С/С++ (СИ)
Спасибо всем за исчерпывающую дискуссию. Есть вопрос о порядке/приоритетности анализа условий. Допустим есть код:
И событие ALARM_ACTIVE всегда предшествует ALARM_COMPL (так построена логика + состояние устанавливаеться 2 источниками ALARM_ACTIVE, а переход к следующему идет только 1, так что само состояние ALARM_COMPL вроде как встречаеться реже). Правильно ли я понимаю, что в таком случае целесообразнее их поменять местами, потому что компилятор "читает" условия справа-налево, и таким образом немного ускорить обработку этого условия ?
Код: Выделить всё
if ((mode == ALARM_ACTIVE) || (mode == ALARM_COMPL))
{
// do something
}
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
ЕМНИП, вообще-то слева направо.
Re: Вопросы по С/С++ (СИ)
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3218828#p3218828"]Есть вопрос о порядке/приоритетности анализа условий.[/uquote]
Есть таблица приоритетов и ассоциативности операторов - снимает напрочь все подобные вопросы, ознакомьтесь - не пожалеете!
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3218828#p3218828"]Допустим есть код:[/uquote]
Внутренние скобки - лишние, поскольку приоритет оператора == равен 7 а у оператора || равен 12. Таблицу приоритетов можно распечатать и заламинировать - чтобы она всегда была перед глазами, а код был чистый и аккуратный.
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3218828#p3218828"]И событие ALARM_ACTIVE всегда предшествует ALARM_COMPL (так построена логика + состояние устанавливаеться 2 источниками ALARM_ACTIVE, а переход к следующему идет только 1, так что само состояние ALARM_COMPL вроде как встречаеться реже). Правильно ли я понимаю, что в таком случае целесообразнее их поменять местами, потому что компилятор "читает" условия справа-налево, и таким образом немного ускорить обработку этого условия ?[/uquote]
Кто про что - а я вновь про таблицу приоритетов
- ассоциативность у обоих используемых операторов "слева-направо". Так что событие ALARM_COMPL будет проверяться только если не произошло ALARM_ACTIVE а не наоборот, как вам нашёптывают "бесы целесообразности".
Есть таблица приоритетов и ассоциативности операторов - снимает напрочь все подобные вопросы, ознакомьтесь - не пожалеете!
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3218828#p3218828"]Допустим есть код:
Код: Выделить всё
if ((mode == ALARM_ACTIVE) || (mode == ALARM_COMPL))
{
// do something
}
Внутренние скобки - лишние, поскольку приоритет оператора == равен 7 а у оператора || равен 12. Таблицу приоритетов можно распечатать и заламинировать - чтобы она всегда была перед глазами, а код был чистый и аккуратный.
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3218828#p3218828"]И событие ALARM_ACTIVE всегда предшествует ALARM_COMPL (так построена логика + состояние устанавливаеться 2 источниками ALARM_ACTIVE, а переход к следующему идет только 1, так что само состояние ALARM_COMPL вроде как встречаеться реже). Правильно ли я понимаю, что в таком случае целесообразнее их поменять местами, потому что компилятор "читает" условия справа-налево, и таким образом немного ускорить обработку этого условия ?[/uquote]
Кто про что - а я вновь про таблицу приоритетов
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Вопросы по С/С++ (СИ)
Спасибо, уже читаю 
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
а я всегда сам придерживался правила и другим советовал: скобки лишними не бывают. тем более что в MISRA вообще запрещается надеяться на приоритеты операторов...Siarzhuk писал(а):Внутренние скобки - лишние
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Вопросы по С/С++ (СИ)
Блин.. А я уже поудалял 
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Ну и напрасно. Не стоит идти против своего удобства, всего-лишь по какому-то совету с форума. Тут дело лично каждого. А компилятору - пофиг.Пока_без_кота писал(а):А я уже поудалял
Я, например, тоже придерживаюсь принципа "скобки лишними не бывают". Во-первых, что самое главное, исключены ошибочные записи. Мы пишем так, как выражение лежит у нас в голове. Во-вторых, улучшается читабельность кода.
Ну а какие плюсы, кроме минусов, от отсутствия "лишних" скобок - мне неведомо
Re: Вопросы по С/С++ (СИ)
Машинный код для машины, исходный - для человека. Поддерживаю предыдущих ораторов в принципе - скобок много не бывает. Автор или другой человек может читать исходный код и забыть о приоритетах, при беглом осмотре это тоже будет притормаживать внимание; разработчики ныне знают более одного языка программирования, вместо кучи памяток о приоритетах можно просто взять и поставить скобки; программирование => математика и эстетичнее выглядит заключённое в скобке выражение - тешит внутреннего перфекциониста.Внутренние скобки - лишние, поскольку приоритет оператора == равен 7 а у оператора || равен 12.
Как говорили: для C/C++ определён порядок слева-направо и перестановкой действительно можно добиться ускорения программы для частых условий.


