간단한 FIFO queue 예제

Posted at 2010/04/22 08:35 // in Programming // by Daniel

#include <stdio.h>

static char qout( void );
static int qin( char in );
static int  qlen ( void );
#define Q_MAX   4
int queue[Q_MAX];
int qhead=0;
int qtail=0;
int main(void)
{
    char io;
    char input;
    int exit=0;
    int state=0;
    char rd;
    printf("simple queue test\n");
    fflush(stdin);
    do {
        switch(state) {
            case 0:
                printf("cmd $ ");
                state = 1;
            case 1:
                fflush(stdout);
                fflush(stdin);
                rd = getchar();
                if (rd==' ' || rd=='\n')
                    continue;
                if (rd=='q') {
                    exit=1;
                    break;
                }
                // get cmd;
                if (rd=='i')
                    state = 5;
                if (rd=='o')
                    state = 10;
                break;
            case 5:
                // input
                printf("input$ ");
                state = 6;
            case 6:
                fflush(stdout);
                fflush(stdin);
                rd = getchar();
                if (rd==' ' || rd=='\n')
                    continue;
                if (rd=='q') {
                    exit=1;
                    break;
                }
                input = rd;
                qin(input);
                printf("h=%d, tail=%d qlen=%d\n", qhead, qtail, qlen());
                state = 0;
                break;
            case 10:
                // get

                printf("%c\n", qout());
                printf("h=%d, tail=%d qlen=%d\n", qhead, qtail, qlen());
                state = 0;
                break;
            default:
                printf("default state??\n");
                exit=1;
        } // switch
    } while(!exit);

    return 0;
}

static int  qlen ( void )
{
    if ( qhead >= qtail )
        return qhead-qtail;
    return qhead+Q_MAX+1-qtail;
}

static int qin( char in )
{
    int tmp_head = qhead;
    tmp_head++;
    if (tmp_head==(Q_MAX+1))
        tmp_head=0;
    if (tmp_head==qtail) {
        // overrun
        fprintf(stderr, "q overrun\n");
        return -1;
    }
    printf("q[%d]<:=%c\n", qhead, in);
    queue[qhead] = in;
    qhead = tmp_head;
    return 0;
}

static char qout( void )
{
    int tmp_tail = qtail;
    if (qtail == qhead) {
        // underrun
        fprintf(stderr, "q underrun\n");
        return '\b';
    }
    qtail = (tmp_tail +1 );
    if (qtail == (Q_MAX+1))
        qtail = 0;
    printf("q[%d]==%c\n", tmp_tail, queue[tmp_tail]);
    return queue[tmp_tail];
}

리팩토링 필요 – 리팩토링 했지만 여기에 게시하진 않음.
크리에이티브 커먼즈 라이센스
Creative Commons License

(C프로그램) 매크로 정의시 안전한 방법

Posted at 2010/04/20 10:31 // in Programming // by Daniel

do { ... } while(0)로 묶기

http://kernelnewbies.org/FAQ/DoWhile0, http://kldp.org/node/41390, http://blog.dasomoli.org/220

안전한 방법은 do{}while(0)로 묶는 것입니다.

#define foo(x) do{ printf(“it’s %d\n”, x); \
                 do_something(x);\
               } while (0)

일반적으로 C에서 매크로를 짜면

#define FOO(x) \
        printf("arg is %s\n", x); \
        do_something_useful(x);

이런 식으로 짜게 됩니다.

그러나 이런 방식은 맹점이 있습니다.

예를 들어

        if (blah == 2)
                FOO(blah);

이렇게 쓰면

        if (blah == 2)
                printf("arg is %s\n", blah);
                do_something_useful(blah);;

이렇게 해석돼 버립니다.

만일 do{ … }while(0)로 만들었다면

if (blah == 2)
        do {
                printf("arg is %s\n", blah);
                do_something_useful(blah);
        } while (0);

이렇게 원하는 대로 해석됩니다.

그렇다고

        #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

이렇게 쓰면

if (x > y)
        exch(x,y);          // Branch 1
else 
        do_something();     // Branch 2

이런 문장이

if (x > y) {                // Single-branch if-statement!!!
        int tmp;            // The one and only branch consists
        tmp = x;            // of the block.
        x = y;
        y = tmp;
}
;                           // empty statement
else                        // ERROR!!! "parse error before else"
        do_something();
이렇게 해석돼 버립니다. –> 컴파일러 에러 발생.
그러므로 do {} while(0)로 묶는 게 최고죠. 그래서 리눅스 커널에서 모든 매크로가 그렇게 돼 있는 겁니다.

매크로에서 쓰는 변수에는 괄호를 꼭 쳐주세요

그리고 한가지 더
매크로에서 쓰는 변수에는 괄호를 꼭 쳐주세요 http://www.oualline.com/style/c06.html

/* Square a number */
#define SQUARE(X) (x * x)
/* Bad practice, no () around parameter */

이렇게 정의하면
a = SQUARE(1 + 3);
-->:
a = (1 + 3 * 1 + 3);
이렇게 돼 버려서 원치 않는 결과가 나옵니다.
/* Square a number */
#define SQUARE(X) ((x) * (x))
이러면
a = ((l + 3) * (1 + 3));
이렇게 잘 나오겠지요.
크리에이티브 커먼즈 라이센스
Creative Commons License

Function pointer

Posted at 2008/11/14 16:33 // in Programming // by Daniel

function pointer 사용법 간단 정리

> 선언
int형을 리턴하며 int형 인자 하나를 받는 함수를 포인터 형식으로 선언하는 경우
    int (*myhandler)( int );

> 할당
  int myfunction( int );
이런 형식의 함수가 있을 때
    myhandler = myfunction;
이렇게 하면 됨

> 실행
    result = myhandler(a);
  또는
    result = (*myhandler)(a);
로 쓴다.

> 인자로 넘길 때
    void pass_it( int (*myfp)(int) );
  이런식으로 씀.

참조 http://oopweb.com/cpp/documents/functio ··· fpt.html

크리에이티브 커먼즈 라이센스
Creative Commons License