Страница 163 из 386

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

Добавлено: Вт авг 13, 2013 12:36:14
YS
Ввести глобальный флаг.

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

play()
{

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

status|=TIMER_NOT_READY;

}
}

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

Добавлено: Вт авг 13, 2013 12:45:22
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);

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

Добавлено: Вт авг 13, 2013 13:06:38
Psych
С помощью флажков можно ваабще кучу функций кода объединить в одну. Делают же наоборот--разбивают на более мелкие части.

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

Добавлено: Вт авг 13, 2013 13:20:24
ploop
так шо без GOTO никак ?
а ведь некоторые вопиют что это дурной тон :)) :wink: :))
Я и говорю - как, да ещё как! Моя мысль была "... если хочется влепить goto, значит надо пересмотреть логику". В 99.999% случаев есть более элегантное решение.

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

Добавлено: Вт авг 13, 2013 13:40:45
Аlex
Desutorakuta писал(а): Но это ещё более дурной тон.
Разрешите поинтересоваться, откуда такие сведения ?
Я на нём (setjmp) сделал вполне нормально-работающий планировщик (кстати, он как раз и нужен вопрошающему). Просветите, а то вдруг я пишу в стиле говнокода, сам не зная этого ... :)

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

Добавлено: Вт авг 13, 2013 15:36:32
Desutorakuta
Ну - если нормально работающий, значит не говнокод. На чём бы человек не писал, какие функции не применял - если программа работает как положено, она написана правильно.

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

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

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

Добавлено: Ср авг 14, 2013 21:42:42
FreshMan
Аlex писал(а):
FreshMan писал(а):подскажите пожалуйста, если я при определенном услови, с помощью оператора return, выхожу из ф-ции в основной цикл то как мне потом вернутся в ф-цию и продолжить с того места где я ранее прервал выполнение ?
http://computerlib.narod.ru/html/setjmp.htm
http://ru.wikipedia.org/wiki/Setjmp.h
пытаюсь вникнуть в суть темы......, обясните пожалуйста на простом крестьянском языке чем GOTO отличается от setjmp кроме того что последняя сохраняет состояние процесса ?

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

Добавлено: Ср авг 14, 2013 21:49:20
Desutorakuta
Это кардинальное отличие!

Кроме того по GOTO нельзя перейти в соседнюю функцию.

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

Добавлено: Ср авг 14, 2013 22:02:23
FreshMan
а с помощью longjmp и setjmp, если я правильно понимаю, можна выйти хоть из n-го вложения, блока ?

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

Добавлено: Ср авг 14, 2013 22:07:29
Аlex
Выйти никуда с их помощью нельзя. Один (setjmp) устанавливает точку возврата, с сохранением состояние, а второй (longjmp) - восстанавливает сохранённое состояние, вместе со счётчиком команд, по этому и происходит "прыжок" в то-же место, где было сохранено состояние.

ЗЫ: Состояние сохраняется в буфер типа jmp_buf, передаваемое параметром в эти макросы. По этому, таких состояний можно делать множество. Это так, для информации...

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

Добавлено: Ср авг 14, 2013 22:10:20
Desutorakuta
Если мне не отшибло склероз, то переход внутри вложенных блоков одной функции не лимитируется. - По гоуту тоже можно выйти из n-вложенного цикла (По крайней мере на практике обычно работает)

А вот переходы между функциями - этого GOTO не может, так как ломается стек. SetJump же обеспечивает верный переход сохранением стека.

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

Добавлено: Ср авг 14, 2013 22:31:56
А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 для каждой из них, и вперёд ...

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

Добавлено: Ср авг 14, 2013 23:07:27
shads
Аlex писал(а):Один (setjmp) устанавливает точку возврата, с сохранением состояние, а второй (longjmp) - восстанавливает сохранённое состояние, вместе со счётчиком команд, по этому и происходит "прыжок" в то-же место, где было сохранено состояние.
ВАУ..... это все стандартный Си ?
Или это уже от лукавого.....

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

Добавлено: Ср авг 14, 2013 23:09:14
Аlex
Это делает стандартная библиотека Си - SetJmp. Ссылки выше.

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

Добавлено: Ср авг 14, 2013 23:27:17
Jack_A
Desutorakuta писал(а): Пример - попробуйте ка в ассемблере обойтись без Jxx инструкций xD. (Аналог if(x)then goto y же!)
Я думаю, если дизассемблировать Си-шную прошивку от самого лютого ненавистниика GOTO, то там этих GOTO, то-бишь JMP, будет до френа.

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

Добавлено: Вт авг 27, 2013 05:14:10
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]) {

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

Добавлено: Вт авг 27, 2013 05:47:05
Kavka

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

((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
 33333333333333333211111111111111111111
1 - это элемент массива
2 - взятие адреса этого элемента, т.е. получается указатель
3 - приведение типа указателя к указателю на uip_tcpip_hdr

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

Добавлено: Вт авг 27, 2013 06:11:30
pokk
Благодарю за ответ.
3 т.е получается мы как бы массив до элемента UIP_LLH_LEN преобразовали в структуру uip_tcpip_hdr ?

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

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

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

а что бы частично преобразовать надо было указатель(адрес) взять/преобразовать &uip_buf[UIP_LLH_LEN]
Так?

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

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

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

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

В качестве более простого примера можно взять адрес переменной типа long и попросить компилятор работать с этим адресом как с char[4]. Получите доступ к long-у как к массиву байтов без масок и сдвигов.

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

Добавлено: Вт авг 27, 2013 08:59:52
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;