контроль нажатой кнопки с помошью case
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Он частично прав. Я делал опыты, уточню работаю в IAR, зависит от количества. Для меня if менее читабельны, и так как разница несущестенна, я плюнул на if, использую switch-case.
Re: контроль нажатой кнопки с помошью case
Вы же понимаете, что это от многого зависит - от компилятора и его флагов сборки, от построения кода. Чтобы проверить разные варианты, нужно понимать в какой ситуации у сказавшего это возникает разница. Поэтому и прошу пример, а не домыслы и рассуждения.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Я и сказал, что он частично прав. Опыты сами ставьте. Потому что я зависимость не помню.
- Ariadna-on-Line
- Это не хвост, это антенна
- Сообщения: 1479
- Зарегистрирован: Вс май 13, 2012 00:01:54
Re: контроль нажатой кнопки с помошью case
Сохранять коды, тем более "полу-фабрикаты", сроду не приходило в голову. Мне интересно "железо", а не тонкости кода и компиляторов. Что видел по ходу "впиханий невпихуемого" в процы - то и запомнил. Switch Case, реально более синтаксически-изящная структура. Но - размеры кода диктуют... Не претендую на истину в последней инстанции.
Re: контроль нажатой кнопки с помошью case
Ну банальный пример, простой:
switch-case занимает 30 байт в итоге что при -Og, что при -Os. if занимает 50 или 44 байт при данных уровнях оптимизации:
Спойлер
Код: Выделить всё
#include <avr/io.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
volatile uint8_t a, b;
int main() {
while (1) {
switch (a) {
case 0:
PORTB = 0;
break;
case 1:
PORTB = 1;
break;
case 2:
PORTB = 1 << 1;
break;
case 3:
PORTB = 1 << 2;
break;
}
if (b == 0)
PORTB = 0;
else if (b == 1)
PORTB = 1;
else if (b == 2)
PORTB = 1 << 1;
else if (b == 3)
PORTB = 1 << 2;
}
}
Спойлер
Код: Выделить всё
00000032 <main>:
break;
case 2:
PORTB = 1 << 1;
break;
case 3:
PORTB = 1 << 2;
32: 94 e0 ldi r25, 0x04 ; 4
volatile uint8_t a, b;
int main() {
while (1) {
switch (a) {
34: 80 91 61 00 lds r24, 0x0061 ; 0x800061 <a>
38: 81 30 cpi r24, 0x01 ; 1
3a: 49 f0 breq .+18 ; 0x4e <__SREG__+0xf>
3c: 30 f0 brcs .+12 ; 0x4a <__SREG__+0xb>
3e: 82 30 cpi r24, 0x02 ; 2
40: 31 f0 breq .+12 ; 0x4e <__SREG__+0xf>
42: 83 30 cpi r24, 0x03 ; 3
44: 29 f4 brne .+10 ; 0x50 <__SREG__+0x11>
break;
case 2:
PORTB = 1 << 1;
break;
case 3:
PORTB = 1 << 2;
46: 98 bb out 0x18, r25 ; 24
break;
48: 03 c0 rjmp .+6 ; 0x50 <__SREG__+0x11>
int main() {
while (1) {
switch (a) {
case 0:
PORTB = 0;
4a: 18 ba out 0x18, r1 ; 24
break;
4c: 01 c0 rjmp .+2 ; 0x50 <__SREG__+0x11>
case 1:
PORTB = 1;
break;
case 2:
PORTB = 1 << 1;
4e: 88 bb out 0x18, r24 ; 24
case 3:
PORTB = 1 << 2;
break;
}
if (b == 0)
50: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <_edata>
54: 81 11 cpse r24, r1
56: 02 c0 rjmp .+4 ; 0x5c <__SREG__+0x1d>
PORTB = 0;
58: 18 ba out 0x18, r1 ; 24
5a: ec cf rjmp .-40 ; 0x34 <main+0x2>
else if (b == 1)
5c: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <_edata>
60: 81 30 cpi r24, 0x01 ; 1
62: 21 f0 breq .+8 ; 0x6c <__SREG__+0x2d>
PORTB = 1;
else if (b == 2)
64: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <_edata>
68: 82 30 cpi r24, 0x02 ; 2
6a: 11 f4 brne .+4 ; 0x70 <__SREG__+0x31>
PORTB = 1 << 1;
6c: 88 bb out 0x18, r24 ; 24
6e: e2 cf rjmp .-60 ; 0x34 <main+0x2>
else if (b == 3)
70: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <_edata>
74: 83 30 cpi r24, 0x03 ; 3
76: f1 f6 brne .-68 ; 0x34 <main+0x2>
PORTB = 1 << 2;
78: 98 bb out 0x18, r25 ; 24
7a: dc cf rjmp .-72 ; 0x34 <main+0x2>
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Пример не корректный.
Swithc-case:
If:
Swithc-case:
Спойлер
Код: Выделить всё
static u08 a;
switch (a)
{
case 0: PORTB = (1<<0);
a = 1;
break;
case 1: PORTB = (1<<1);
a = 2;
break;
case 2: PORTB = (1<<2);
a = 3;
break;
case 3: PORTB = (1<<3);
a = 4;
break;
case 4: PORTB = (1<<4);
a = 5;
break;
case 5: PORTB = (1<<5);
a = 6;
break;
case 6: PORTB = (1<<6);
a = 7;
break;
case 7: PORTB = (1<<7);
a = 0;
break;
}
Спойлер
Код: Выделить всё
if (a == 0) {PORTB = (1<<0); a = 1;}
if (a == 1) {PORTB = (1<<2); a = 2;}
if (a == 2) {PORTB = (1<<3); a = 3;}
if (a == 3) {PORTB = (1<<3); a = 4;}
if (a == 4) {PORTB = (1<<4); a = 5;}
if (a == 5) {PORTB = (1<<5); a = 6;}
if (a == 6) {PORTB = (1<<6); a = 7;}
if (a == 7) {PORTB = (1<<7); a = 0;}
Re: контроль нажатой кнопки с помошью case
И всё равно на gcc с -Os у меня switch занимает меньше. 84 байта против 114.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Я уже подробностей не помню. Подобный диалог и подобные примеры были несколько лет назад на форуме easyelectronics. Для меня switch-case более читабелен и структурирован.
Re: контроль нажатой кнопки с помошью case
Может это было в какой-нибудь старой версии компилятора? Или уровень оптимизации низкий для упрощения отладки стоял. Или еще какой нюанс.
Demiurg, кстати вот ваш пример как раз таки странный, в отсутствии else if и сменой a внутри блоков
Demiurg, кстати вот ваш пример как раз таки странный, в отсутствии else if и сменой a внутри блоков
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Ну, да ретурны забыл. Писал на смарте, потому и так.
А вообще эта ошибка иногда может стоить часов а то и дней разборок в коде. И это касается как switch-case, break return. Так и в данном случае. Я на одном проекте так нарвался. Длинный свитч кейс.
А вообще эта ошибка иногда может стоить часов а то и дней разборок в коде. И это касается как switch-case, break return. Так и в данном случае. Я на одном проекте так нарвался. Длинный свитч кейс.
Re: контроль нажатой кнопки с помошью case
Некоторые IDE, кстати, предупреждают об отсутствии break'ов в конце case'ов, емнип. А вот про if уже вряд ли будут понимать.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: контроль нажатой кнопки с помошью case
Break не всегда нужно ставить. Я иногда намеренно так делаю. Когда установлено новое состояние, тут же идёт новый кейс и код. Иногда делаю так, несколько кейсов списком и код.
Типа такого:
Типа такого:
Спойлер
Код: Выделить всё
//=============
switch (state)
{
case STATE_INIT:
io_init ();
state = STATE_WORK;
case STATE_WORK:
bla-bla ();
state = STATE_X;
break;
}
//=============
//=============
//------------------------------------------------------------------------
case TUI_SERVICE_CHANGE_T_HEAT:
blink_heat ();
break;
//------------------------------------------------------------------------
case TUI_SERVICE_CHANGE_T_FORMOVKA:
blink_form ();
break;
//------------------------------------------------------------------------
case TUI_SERVICE_CHANGE_T_PNEV:
blink_pnev ();
break;
//------------------------------------------------------------------------
case TUI_SERVICE_ENTER_SETT_QUANT:
case TUI_SERVICE_CHANGE_SETT_QUANT:
blink_tirag ();
break;
//------------------------------------------------------------------------
case TUI_SERVICE_ENTER_ADD_CURR_QUANT:
case TUI_SERVICE_ENTER_SUB_CURR_QUANT:
case TUI_SERVICE_CHANGE_CURR_QUANT:
blink_curr_quant ();
break;
case TUI_SERVICE_CHANGE_PART:
case TUI_SERVICE_ENTER_PART:
blink_part ();
break;
//=============
Re: контроль нажатой кнопки с помошью case
Конечно не всегда, я в курсе. Но очень часто. И поэтому IDE предупреждает очень тактично. 