Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
YS
Друг Кота
Аватара пользователя
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05

Сообщение YS »

Ввести глобальный флаг.

Код: Выделить всё

play()
{

if (status & TIMER_NOT_READY)
{
.....
.......
сдесь я запускаю Т2 и выпригиваю с данной ф-ции
}
else
{
сюда я возвращаюсь когда Т2 отсчитает определенное время
.....
......

status|=TIMER_NOT_READY;

}
}
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

Сообщение Desutorakuta »

Совершенно верно, с ГоуТу не поможет, только SetJump. Но это ещё более дурной тон.

Хороший тон в этом случа был бы разбить функцию Play в стиле конечного автомата. Ну что то вроде:

Код: Выделить всё

PlayState state = InitPlay();
for(;;){
  if(Play(state)==PLEASE_SET_TIMER)SetTimer();

  if(TimerInterrupt())PlayInterrupt(state);
}
ReleasePlay(state);
Или в стиле передачи сообщений:

Код: Выделить всё

play(PLAY_INIT);
for(;;){
  witch(play(PLAY_START)){
    case PLAY_PLEASE_SET_TIMER: SetTimer();
  }

  if(TimerInterrupt()) play(PLAY_TIME_OUT);
}

play(PLAY_RELEASE);
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Сообщение Psych »

С помощью флажков можно ваабще кучу функций кода объединить в одну. Делают же наоборот--разбивают на более мелкие части.
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

так шо без GOTO никак ?
а ведь некоторые вопиют что это дурной тон :)) :wink: :))
Я и говорю - как, да ещё как! Моя мысль была "... если хочется влепить goto, значит надо пересмотреть логику". В 99.999% случаев есть более элегантное решение.
Реклама
Эиком - электронные компоненты и радиодетали
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Desutorakuta писал(а): Но это ещё более дурной тон.
Разрешите поинтересоваться, откуда такие сведения ?
Я на нём (setjmp) сделал вполне нормально-работающий планировщик (кстати, он как раз и нужен вопрошающему). Просветите, а то вдруг я пишу в стиле говнокода, сам не зная этого ... :)
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

Сообщение Desutorakuta »

Ну - если нормально работающий, значит не говнокод. На чём бы человек не писал, какие функции не применял - если программа работает как положено, она написана правильно.

Пример - попробуйте ка в ассемблере обойтись без Jxx инструкций xD. (Аналог if(x)then goto y же!)

Хороший тон в программировании определяется, в общем то, единственным факторами - насколько его легко прочитать другому человеку. Отсюда требование избегать GOTO, как потенциального средства запутывания кода. Отсюда же требование избегать ещё более свободный и менее очевидный setJmp.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

Аlex писал(а):
FreshMan писал(а):подскажите пожалуйста, если я при определенном услови, с помощью оператора return, выхожу из ф-ции в основной цикл то как мне потом вернутся в ф-цию и продолжить с того места где я ранее прервал выполнение ?
http://computerlib.narod.ru/html/setjmp.htm
http://ru.wikipedia.org/wiki/Setjmp.h
пытаюсь вникнуть в суть темы......, обясните пожалуйста на простом крестьянском языке чем GOTO отличается от setjmp кроме того что последняя сохраняет состояние процесса ?
Tell Me The Truth
Встал на лапы
Аватара пользователя
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

Сообщение Desutorakuta »

Это кардинальное отличие!

Кроме того по GOTO нельзя перейти в соседнюю функцию.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

а с помощью longjmp и setjmp, если я правильно понимаю, можна выйти хоть из n-го вложения, блока ?
Tell Me The Truth
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Выйти никуда с их помощью нельзя. Один (setjmp) устанавливает точку возврата, с сохранением состояние, а второй (longjmp) - восстанавливает сохранённое состояние, вместе со счётчиком команд, по этому и происходит "прыжок" в то-же место, где было сохранено состояние.

ЗЫ: Состояние сохраняется в буфер типа jmp_buf, передаваемое параметром в эти макросы. По этому, таких состояний можно делать множество. Это так, для информации...
Встал на лапы
Аватара пользователя
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

Сообщение Desutorakuta »

Если мне не отшибло склероз, то переход внутри вложенных блоков одной функции не лимитируется. - По гоуту тоже можно выйти из n-вложенного цикла (По крайней мере на практике обычно работает)

А вот переходы между функциями - этого GOTO не может, так как ломается стек. SetJump же обеспечивает верный переход сохранением стека.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Вот Вам кодик, для примера

Код: Выделить всё

//********************************************************
#include "SetJmp.h"

jmp_buf         j_buf;

//********************************************************
void mfun(void){
while(1){
    if(!setjmp(j_buf)){     // Сохраняем точку возврата
        return;             // и выходим из функции
    }
    //..................
    Nop();                  // сюда вернёмся после longjmp
    //..................
    if(!setjmp(j_buf)){     // Сохраняем точку возврата
        return;             // и выходим из функции
    }
    //..................
    Nop();                  // сюда вернёмся после longjmp
    //..................
    if(!setjmp(j_buf)){     // Сохраняем точку возврата
        return;             // и выходим из функции
    }
    //..................
    Nop();                  // сюда вернёмся после longjmp
    //..................
}
}
//********************************************************
void main (void){

mfun();                 // Первый вызов ф-ии, для первого
                        // сохранения точки прыжка
while(1){
    longjmp(j_buf, 1);  // Прыгаем в сохранённую точку
    Nop();              // Сюда будем возвращаться по return
}
}
//********************************************************
ЗЫ: Кстати, почти готовый планировщик :) Осталось добавить ещё функций и буферы jmp_buf для каждой из них, и вперёд ...
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Аlex писал(а):Один (setjmp) устанавливает точку возврата, с сохранением состояние, а второй (longjmp) - восстанавливает сохранённое состояние, вместе со счётчиком команд, по этому и происходит "прыжок" в то-же место, где было сохранено состояние.
ВАУ..... это все стандартный Си ?
Или это уже от лукавого.....
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Это делает стандартная библиотека Си - SetJmp. Ссылки выше.
Друг Кота
Аватара пользователя
Сообщения: 6332
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Desutorakuta писал(а): Пример - попробуйте ка в ассемблере обойтись без Jxx инструкций xD. (Аналог if(x)then goto y же!)
Я думаю, если дизассемблировать Си-шную прошивку от самого лютого ненавистниика GOTO, то там этих GOTO, то-бишь JMP, будет до френа.
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Здравствуйте, что такой макрос делает ? В моём понимании он из принятого буфера выделяет ip адреса по структуре тд но вот
uip_buf[UIP_LLH_LEN] это же всего 1 элемент.

Код: Выделить всё

#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
uip_tcpip_hdr это структура заголовка IP
Спойлер

Код: Выделить всё

/* The TCP and IP headers. */
typedef struct {
  /* IP header. */
  u8_t vhl,
    tos,
    len[2],
    ipid[2],
    ipoffset[2],
    ttl,
    proto;
  u16_t ipchksum;
  u16_t srcipaddr[2],
    destipaddr[2];

  /* TCP header. */
  u16_t srcport,
    destport;
  u8_t seqno[4],
    ackno[4],
    tcpoffset,
    flags,
    wnd[2];
  u16_t tcpchksum;
  u8_t urgp[2];
  u8_t optdata[4];
} uip_tcpip_hdr;
uip_buf это приёмный буфер

Дальше это всё используется так (сравнивается принятый IP адрес со своим)

Код: Выделить всё

  if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
     BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
     BUF->destipaddr[0] == FBUF->destipaddr[0] &&
     BUF->destipaddr[1] == FBUF->destipaddr[1] &&
     BUF->ipid[0] == FBUF->ipid[0] &&
     BUF->ipid[1] == FBUF->ipid[1]) {
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Код: Выделить всё

((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
 33333333333333333211111111111111111111
1 - это элемент массива
2 - взятие адреса этого элемента, т.е. получается указатель
3 - приведение типа указателя к указателю на uip_tcpip_hdr
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Благодарю за ответ.
3 т.е получается мы как бы массив до элемента UIP_LLH_LEN преобразовали в структуру uip_tcpip_hdr ?

походу это я описал про такое

Код: Выделить всё

uip_eth_hdr *BUF = (uip_eth_hdr*)uip_buf;
но тут весь массив преобразовали в структуру.

а что бы частично преобразовать надо было указатель(адрес) взять/преобразовать &uip_buf[UIP_LLH_LEN]
Так?
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Во-первых, не "до", а начиная с элемента в ячейке с номером взятом из UIP_LLH_LEN.
Во-вторых не преобразовывается, а указывается компилятору как работать с конкретным указателем. Расклад в памяти остаётся таким как был.
Берётся адрес в памяти и говориться компилятору, что с данными по этому адресу работать как со структурой. Ничего в памяти не копируется.
При этом порядок полей в структуре просто "раскладывается" на указанную область памяти. За соответствием полей надо следить самому.

Код: Выделить всё

                   uip_tcpip_hdr 
                   -------------------
                   | | | | | | | | | |     
       -------------------------------------------------------
uip_buf| | | | | | |*| | | | | | | | | | | | | | | | | | | | |
       -------------------------------------------------------
                    ^
                    UIP_LLH_LEN
Попадает ли весь массив под структуру? Если количество байт у структуры и у массива совпадают, то да. Но это не обязательно. Например как на схеме выше.

В качестве более простого примера можно взять адрес переменной типа long и попросить компилятор работать с этим адресом как с char[4]. Получите доступ к long-у как к массиву байтов без масок и сдвигов.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Код: Выделить всё

Во-первых, не "до", а начиная с элемента в ячейке с номером взятом из UIP_LLH_LEN.
Благодарю а то со своим понимание "ДО" сразу затупил на следующей строчке

Код: Выделить всё

#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
:))
Во-вторых ...
Я примерно это так и представлял только правильно написал. С чем-то похожим сталкивался когда с переменной float воевал/
В качестве более простого примера можно взять адрес переменной типа long и попросить компилятор работать с этим адресом как с char[4]. Получите доступ к long-у как к массиву байтов без масок и сдвигов.
Это будет так ?

Код: Выделить всё

typedef struct {

        char b[3];

} U8long;


U8long *u8 = (U8long*)h;
Ответить

Вернуться в «Разные вопросы по МК»