'분류 전체보기'에 해당되는 글 251건

  1. 2012.02.04 enum 타입 c vs c++
  2. 2012.01.30 system vs exec
  3. 2012.01.25 process & signal
  4. 2012.01.03 Linux: umask
  5. 2011.11.29 error: invalide storage class for function 'xxxx'
  6. 2011.11.29 대상체의 기억수명
  7. 2011.11.28 열거, enum, 이놈
  8. 2011.11.09 루틴: 루틴이름, 루틴길이,
  9. 2011.11.09 루틴: 설계
  10. 2011.11.09 전처리기 (1)
프로그래밍/C2012. 2. 4. 14:58



라고 enum 타입을 정의 했다고 치자.
그렇다면 이 enum 타입을 리턴하는 함수는 어떻게 정의 할까? c++ 라면 Food라고 해 줄 수 있지만, c에서는 아쉽게도 다음과 같이 써 줘야 한다.



이렇게 하는게 싫다면 typedef 으로 정의해 주면 된다.


'프로그래밍 > C' 카테고리의 다른 글

C의 역사  (0) 2012.02.19
enum vs #define vs const  (0) 2012.02.05
system vs exec  (0) 2012.01.30
process & signal  (0) 2012.01.25
error: invalide storage class for function 'xxxx'  (0) 2011.11.29
Posted by code cat
프로그래밍/C2012. 1. 30. 08:07

system 으로 쉘 명령어를 실행시키거나 프로세스를 실행시키는건 대체적으로 좋지 않은 방법이다. 

이는 system 이 동작하기 위해 먼저 쉘을 실행시키기 때문이다. 이렇게 시작된 쉘은 각 설치된 쉘의 환경등에 따라 다른 동작성을 보일 수 있기 때문이다. 


그래서 보통 대체적으로 쓰이는 것이, exec 이며 exec 계열은 다음과 같이 나뉘어진다. 
execl, execle, execlp
execv, execve, execvp

그러나 이런 exec 또한 프로세스를 실행시킨 뒤 에러가 나지 않는 한 리턴되지 않는다.

즉,우리가 처음 시작한 프로세스에서 여러개의 프로세스를 실행시키기에는 부적합하다는 것이다. 


그래서 대신 자식 프로세스를 생성하거나 쓰레드를 생성하는 것이다

'프로그래밍 > C' 카테고리의 다른 글

enum vs #define vs const  (0) 2012.02.05
enum 타입 c vs c++  (0) 2012.02.04
process & signal  (0) 2012.01.25
error: invalide storage class for function 'xxxx'  (0) 2011.11.29
대상체의 기억수명  (0) 2011.11.29
Posted by code cat
프로그래밍/C2012. 1. 25. 18:34
signal 라이브러리 함수은 다음과 같다.

void (*signal(int sig, void (*func)(int)))(int);

예)
위에 예제처럼 printf를 시그널 핸들러 함수에서 하는건 안전하지 않다.
그보다는, 시그널 핸들러가 플래그를 set하고 메인 함수에서 flag를 체크해서 그에 맞게 처리하는게 좋다.

하지만 X/Open 및 UNIX specifications은 sigaction이라는 프로그래밍 인터페이스를 사용하기를 권장한다.

#include <signal.n>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

설명
sigaction structure는 다음의 멤버들을 가지고 있다.
    void (*) (int) sa_handler  /* 함수, SIG_DFL, SIG_IGN*/
    sigset_t sa_mask            /* sa_handler에서 블록할 signal*/
    int sa_flags                    /* signal action modifier*/

sigaction 함수는 시그널 sig와 연관된 action을 설정한다.
 - oact가 null이 아닌 경우, sigaction은 이전의 signal action을 쓴다.
 -- act가 null인 경우, 아무 일도 안한다.
 -- act가 null이 아닌 경우, 시그널을 위한 action이 설정된다.

act에 의해 가리켜지는 sigaction 안에 있는 sa_handler는 시그널 sig가 들어오면 불려지는 함수에 대한 포인터이다.
sa_mask는 sa_handler가 불리기 전에 프로세스의 시그널 mask에 추가될 시그널 세트들을 설정한다.(이 세트들은 블록되어 프로세스로 전달되지 않는 시그널들이다.  sa_mask를 사용하면 race condition을 방지할 수 있다)

Return value
sigaction이 성공적일 경우, 0을 리턴하고 아닌 경우 -1을 리턴한다. A

'프로그래밍 > C' 카테고리의 다른 글

enum 타입 c vs c++  (0) 2012.02.04
system vs exec  (0) 2012.01.30
error: invalide storage class for function 'xxxx'  (0) 2011.11.29
대상체의 기억수명  (0) 2011.11.29
열거, enum, 이놈  (0) 2011.11.28
Posted by code cat
리눅스2012. 1. 3. 08:59

(출처: Beginning Linux Programming 3rd edition)


알면서도 안 써먹는 거 같아서... 써 놓으면 생각날때 써먹을 수 있을거 같아서 쓴다.

umask는 open 혹은 create 호출을 통하여 파일을 만들 때 mode 매개변수를 umask와 비교한다.

mode 매개변수와 umask에 공통으로 설정되어 있는 비트는 제거된다.  결국 사용자는 "파일을 만드는 프로그램이 다른 사용자의 쓰기 권한을 요청하더라도 이 권한을 가지고 있는 어떤 파일도  만들면 안된다"라고 이야기하는 환경을 설정할 수 있다.


비록 그렇다고 해도 사용자나 프로그램이 chmod 명령을 연속으로 사용하여 다른 사용자의 쓰기 권한을 추가하는 것까지 방지할 수는 없다.  그렇지만 새로 생성하는 모든 파일에 대해 권한을 검사하고 설정하는 노력을 사용자로부터 덜어줄 수는 있다.


Posted by code cat
프로그래밍/C2011. 11. 29. 20:39

이런 에러가 나는 경우는, c는 함수가 다른 함수 안에나 블록 속에 정의되는 것을 허락하지 않기 때문이다.

바꿔 쉽게 말하자면, xxxx라는 함수 위에 있는 함수나 블록 중에서 }를 닫는 것을 잊어 먹었을 경우인 것이다.

{}을 잘 닫았는지 확인하고, 만약 혹시라도 블록 안에나 다른 함수에서 함수를 정의하려고 한다면, 이건 C 표준이 허락치 않는 걸 삽질하려는 것이다.

'프로그래밍 > C' 카테고리의 다른 글

system vs exec  (0) 2012.01.30
process & signal  (0) 2012.01.25
대상체의 기억수명  (0) 2011.11.29
열거, enum, 이놈  (0) 2011.11.28
전처리기 (1)  (0) 2011.11.09
Posted by code cat
프로그래밍/C2011. 11. 29. 14:51

참조(C 펀더멘탈, 전웅 저, 한빛 미디어)

기억수명(storage duration, extent, lifetime)은 대상체에만 적용되는 개념이다.  대상체의 기억수명이란 어떤 대상체가 값을 저장하기 위해 할당받은 메모리를 차지하고 있는 시간을 말한다.  다시 말해, 프로그램에 선언된 모든 대상체가 시작부터 종료까지 계속 메모리에 상주하는게 아니라, 대상체의 기억수명이라는 것에 따라, 어느 순간 할당(alloc)받고  해제(dealloc)하는 것을 말한다.

C가 제공하는 대상체의 기억 수명은,

  • static storage duration 정적 기억수명
  • auto storage duration  자동 기억 수명
  • allocated storage duration  할당 기억 수명

이중 allocated storage duration 할당 기억 수명은 프로그램의 위치에 상관없이 메모리를 원하는 순간 요청하고 해제할 수 있는 기억 수명이다.  malloc()이 대표적인 예가 되겠다.

정적 기억수명과 자동 기억수명, 그리고 할당 기억수명의 가장 큰 차이는 할당되는 대상체의 크기가 프로그램 실행 중에 고정되어 있는지 여부이다.  언어 부분에 의해 지원되는 두 종류(자동, 정적)의 기억수명을 갖는 대상체는 프로그램이 실행되기 전에 그 크기가 상수로 고정되어 있어야 한다.

정적 기억수명을 갖는 대상체는 프로그램이 시작해서 종료될 때까지 메모리에 항상 존재한다.

자동 기억수명을 갖는 대상체는 그 대상체를 지칭하는 통용 범위와 운명을 함께 한다.

Posted by code cat
프로그래밍/C2011. 11. 28. 14:48

(참조: C언어 펀더멘탈, 전웅 저, 한빛 미디어)


이놈은 농담이고, 열거자에 대한 여러가지 알아야 할 것들을 적어 보았다.


동일한 값을 나타내도록 선언 할 수 있음

    enum food { apple = 2, orange = 2, banana = 2 };


대소관계를 순서로 가질 필요도 없음

    enum food { apple = 2, orange = 3, banana = 1};


열거상수로 선언되는 명칭은 일반 명칭과 동일한 이름 공간을 사용

    enum food { apple = 2, orange = 3, banana = 4};

    int apple; /* wrong */


값이 지정되어 있지 않은 경우,

첫번째 열거자면 0으로 값을 갖는다

첫번째가 아니라면 앞의 값보다 하나 큰 값을 가진다.


열거형에는 불완전형의 개념이 존재하지 않는다.

    enum food *p; /* wrong */

    enum food;     /* wrong */


열거형을 위해 사용할 정수형은 다음과 같다.

(signed/unsigned) char

signed/unsigned short int

signed/unsigned int

signed/unsigned long int


열거의 올바른 사용법

가장 올바르게 열거를 사용하기 위해서는 열거를 마치 구조체나 공용체처럼 완전히 독립된 데이터형으로 다루어야 한다. 그러기 위해선, 다음과 같이...

  • 열거형 대상체에는 반드시 그 열거형이 멤버로 갖는 열거 상수만을 대입한다.
  • 열거형 대상체를 다른 정수형의 값과 함께 연산에 사용하는 경우, 반드시 적절한 캐스트 연산자와 주석을 통해 의도를 분명히 밝힌다.
  • 열거형 대상체에 해당 열거형의 열거 상수가 아닌 임의의 정수값을 대입할 필요가 있다면, 그 정수값을 열거형의 멤버로 추가하는 것을 고려한다.
  • 서로 다른 열거형 사이에 대입이나 연산은 피한다.



Posted by code cat

출처: Code Complete 2, 김도균 감수, 정보 문화사


좋은 루틴 이름:

루틴이 하는 모든 것을 표현하라

의미가 없거나 모호하거나 뚜렷한 특징이 없는 동사들을 피하라

루틴 이름을 숫자만으로 구분하지 마라

필요한 길이만큼 루틴의 이름을 만들라 : 9~ 15자 사이가 좋다.

함수의 이름을 지을 때, 리턴 값에 대해서 설명하라 : cos(), customerId.Next() 등

프로시저의 이름을 지을 때, 확실한 의미를 가지는 동사 다음에 객체를 사용하라. : 동사+객체 PrintDocument()

반의어를 정확하게 사용하라 : FileOpen(), FileClose()

공통적인 연산을 위한 규약을 만들라 : employee.Get.Id(), emploee.Get.Age()


루틴의 길이:

루틴의 길이는 200줄을 넘기지 않도록 노력한다.


루틴의 매개변수 사용법:

매개변수를 입력-수정-출력 순서로 입력한다.

 매개변수를 무작위로, 또는 알파벳 순으로 정렬하는 것보다는, 입력만 가능한 것을 첫번째로, 입출력이 가능한 것을 두 번째로, 출력만 가능한 것을 세 번째로 나열하라.  이것은 C라이브러리의 규약과 충돌된다. (수정되는 매개변수를 처음에 입력한다)

고유한 in과 out키워드 생성을 고려해 보라

여러 루틴이 유사한 매개변수를 사용한다면, 유사한 매개변수들을 일관된 순서로 입력하라

모든 매개변수를 사용하라 : 사용하지 않으면 제거하라. 이것은 잠재적인 error의 요인이 된다.

상태나 오류 변수를 마지막에 입력한다.

루틴의 매개변수를 작업용 변수로 사용하지 마라.

매개변수에 대한 인터페이스 가정을 문서화하라.

매개변수에 사용할 입력, 수정, 출력 이름 규약을 고려하라.


'소프트웨어 엔지니어링' 카테고리의 다른 글

[용어] Payload란?  (0) 2014.07.18
[terminology] reap  (0) 2014.01.11
아파치 라이센스 2.0 사용법  (0) 2012.04.12
루틴: 설계  (0) 2011.11.09
Posted by code cat

출처: Code Complete 2, 김도균 감수, 정보 문화

응집성을 높여라

: cosine()하면 오로지 하나, 코사인 계산을 위한 것이다. 그러나 만일 cosineAndTan()하면 한가지 이상의 작업을 하므로 응집성이 떨어진다. 목표는 한가지 일을 잘하도록 하는 것이다.  

우리는 기능성 응집성이 강한 루틴을 작성하도록 해야 한다.

루틴을 작성할 때, 주의 할 점이라면,

  • 순차적 응집성을 피하라.  이것은 루틴이 특정한 순서대로 수행되어야 하고 단계별로 데이터를 공유하여 동시에 수행될 때, 그리고 완전한 기능을 제공하지 못하는 연산ㅇ을 포함할때 존재한다.  예를 들어, 출생일을 입력값으로  받아, 나이와 퇴직일을 계산하는 루틴이 있다고 하자.  만일 이 루틴이 나이를 계산하고 그 결과 값을 토대로 퇴직일을 계산한다면 이 루틴은 순차적 응집성을 지닌다.  반면에 만약에 루틴이 나이를 계산하고 동일한 출생일 데이터를 사용하는 완전히 독립적인 계산 방법으로 퇴직일을 계산한다면 이 루틴은 통신적 응집성만 갖는다.  그러므로 우리는 나이계산 루틴과 퇴직일 계산 루틴을 생성해, 퇴직일 루틴이 나이 루틴을 호출하도록 한다. 그러면 이 두 루틴은 기능성 응집을 갖는다.

  • 통신적 응집성은 루틴에 있는 연산들이 동일한 데이터를 사용하지만 서로 아무런 연관이 없을 때 발생한다.  만약 어떤 루틴이 요약 보고서를 출력하고, 루틴으로 넘어온 요약 데이터를 다시 초기화한다면, 이 루틴은 통신적 응집을 갖는다. 이 루틴에 보다 나은 응집성을 제공하기 위해서는 요약 데이터가 생성된 곳 근처에서 다시 초기화되어야 하며, 보고서 출력 루틴 안에 있어서는 안된다.  이 연산들을 개별적 루틴으로 나누어라.

  • 일시적 응집성은 연산들이 동시에 수행하기 때문에 한 루틴안에 결합되어 있는 경우다.  예를 들면, startUp()이나 showDown()들이겠다.  이 루틴을 효율적으로 만들기 위해서는 응집된 루틴이 연산들을 직접적으로 하기보다는, 다른 루틴을 호출하는 것으로 만드는게 좋다.

다음은 수용하기 어려운 응집성의 종류이다.

  • 절차적 응집성은 루틴에 있는 연산들이 특정한 순서대로 수행될 때 발생한다.  예를 들어 데이터를 순차적으로 입력 받을때, GetFirstName(), GetLastName()같이 부르고, 이 루틴은 연산들을 특정한 순서대로 사용하지만, 연산들이 결합 할 필요는 없기 때문에 절차적 응집성을 갖는다.  다시 말하면,GetFirstPartOfEmployeeData() 대신, GetEmployee()같은 루틴을 작성하라.

  • 논리적 응집성은 여러가지 연산들이 한 루틴에 채워져 있고, 연산 중 하나가 루틴에 전달되는 제어 플래그에 의해서 선택될 때 발생한다. 만일 이벤트 핸들러의 역활로 사용된다면 좋은 설계로 볼 수 도 있으니 주의하자.

  • 우연성 응집은 루틴에 있는 연산들이 서로를 인식할 만한 관계를 가지고 있지 않을 때 발생한다.



'소프트웨어 엔지니어링' 카테고리의 다른 글

[용어] Payload란?  (0) 2014.07.18
[terminology] reap  (0) 2014.01.11
아파치 라이센스 2.0 사용법  (0) 2012.04.12
루틴: 루틴이름, 루틴길이,  (0) 2011.11.09
Posted by code cat
프로그래밍/C2011. 11. 9. 10:26

출처: C 언어 펀더멘탈, 전웅 저, 한빛미디어

#define int2hex(n) ((int)"0123456789ABCDEF"[(int)(n)])


int (int2hex)(int n)

{

    return "012345678ABCDEF"[n];

}


(int2hex)를 괄호로 둘러쌓아, 만일

int int2hex(int n)

으로 함수를 정의했을 때 매크로로 확장되는 걸 방지 할 수 있다.  함수의 주소를 취할 때도 함수명만 사용하거나 함수명에 번지 연산자를  붙인 형태를 사용하기 때문에 전처리 과정에서 매크로로 확장되지 않는다.

만약 필요에 따라 매크로가 아닌 실제 함수를 호출하고 싶다면, #undef 지시자를 사용하거나 다음과 같은 형태의 함수 호출 수식을 사용할 수 있다.

(int2hex)(12);


한편 매크로 함수를 사용하는 또 다른 경우는, 이미 구현되어 있는 함수에서 일정 개수의 인자를 특정 값으로 고정해 사용하는 경우이다.  특히 이는 라이브러리를 구현할 때 많이 사용하는 방법이다.  예를 들어 line()이라는 함수가 구현되어 있다고 하자.

#define line_h(x, y, len, c, s) (line((x),(y),(x)+(len)-1, (y),(c),(s)))

#define line_v(x, y, len, c, s) (line((x),(y),(x),(y)+(len)-1,(c),(s)))

등으로 간단히 매크로로 대체할 수 있다.


여러 수식을 하나의 수식으로 만들어 매크로 함수에 담는 것은 쉼표 연산자를 사용하면 간단하다.  특히 쉼표 연산자는 피연산자로 주어진 수식 사이에서 평가순서와 시퀀스 포인트를 보장해 주기 때문에 연속적인 수식문과 동일하게 사용된다.

#define func_seq() (func1(a,b,c,d),\

    func2(a,b,c,d),\

    func3(a,b,c,d))


매크로 함수 사용시에 세미콜론의 사용여부를 다음과 같이 간단히 처리 할 수 있다.

#define SMT(test, ret) \

    do{                       \

     if(!(test)){             \

        set_error(SMT_ERROR); \

        return ret;

    }

}while(0)

Posted by code cat