C3SG
Clunix Wiki
목차 |
Clunix C Coding Style Guide
이 문서는 Clunix S/W 개발 프로그래밍시 바람직한 C 프로그래밍 코드 작성법을 제시한다. 코딩 스타일은 매우 개인적인 것이지만 S/W 개발이나 보수유지에 필요한 개발자들간의 원할한 협력을 도모하는데 있어서 코딩 스타일에 대한 원칙적인 합의는 중요하다. GNU indent로 해결가능한 부분에 대하여는 개발자의 자유로운 코딩 스타일을 인정하는 권고사항으로 한다.
General
화면의 폭은 80 column을 가정한다. 라인의 길이는 80 column을 지키도록 하며, 부득이한 경우나 줄바꿈이 혼동을 주는 경우는 예외로 한다.
Indentation
Indentation에 관하여는 개인적인 취향이며, indent 도구를 이용하여 충분히 해결할 수 있는 부분이므로 권고사항으로 둔다.
Indentation은 8 공백글자, 1 tab을 사용하는 것을 권고한다. 블럭의 시작과 끝을 명확히 구분하는 것이 좋다. 또한 소스코드가 왼쪽으로 치우치지 않고 화면에 전체적으로 분산되어 가독성을 높일 수 있다. 8 공백글자에 대응하는 1 tab의 indentation이 너무 커서 한행의 표현력이 떨어지는 문제점은 다르게 말하면 과다한 indentation depth가 오히려 가독성을 떨어지게 하는 문제로 작용할 수도 있게 된다. 따라서 8칸의 indentation이 indentation depth를 줄이도록 개발자의 습관을 유도할 수 있다.
Placing Braces
- K&R 형식을 따른다.
- opening brace는 행의 마지막에 두며, closing brace는 행의 처음에 오도록한다.
if (condition) { if_true; }
- opening brace 앞에는 공백문자 하나를 둔다.
- 그러나 함수의 body를 정의하는 opening brace는 다음행의 처음에 오도록 한다.
void function(int x) { function_body; }
- closing brace는 단독으로 하나의 행을 구성하지만 하나의 문장을 구성하는 다른 부분이 연속해서 closing brace 부분 뒤에 나오는 경우에는 closing brace와 같은 행에 연속되는 부분이 나올 수 있다. "while"문이나 "if-else" 문이 그러한 예이다.
do { body_of_do_loop; } while (condition); if (a == b) { if_true; } else if (a > b) { if_true_another; } else { if_else; }
이 때 closing brace와 연결되는 문장의 일부분은 공백 문자 하나를 둔다.
Symbol Naming
- 파일이름, 변수명, 함수명 등의 symbol은 소문자, 숫자, '_' 로 이루어진다.
- #define MACRO 문의 매크로 상수나 함수는 대문자, 숫자, '_' 로만 구성한다.
- word seperator로는 '_' 를 사용하며 대소문자를 섞어쓰는 형식은 금한다.
- type definition된 type의 이름은 "_t" suffix를 가진다.
typedef struct list_item { int ref; char name[NAME_MAX]; char val[VAL_MAX]; struct list_item *next; } list_item_t;
- symbol은 가급적 의미있는 단어를 사용한다.
- 모듈내에서 사용되는 변수나 함수는 반드시 static으로 선언한다.
- 외부로 Export되는 심볼은 그 모듈이나 패키지를 식별할 수 있는 prefix symbol을 반드시 이용하도록 한다.
- 만약 init_user라는 함수 심볼이 모듈 외부로 Export되는 경우에는 해당 모듈 패키지를 식별할 수 있는 clx같은 prefix 문자열을 이용하여 clx_init_user >같은 심볼로 사용하는 것이 모듈 외부에서 사용될 때 혼란을 방지할 수 있다.
- 함수이름은 동사 혹은 동사+명사 형식의 조함으로 구성하는 것을 권장한다.
- Boolean 형식의 반환값을 제공하는 함수 이름은 "is_" prefix를 써서 함수이름을 정하는 것을 권장한다.
- 변수이름은 명사 혹은 수식어+명사 형식의 조합으로 구성하는 것을 권장한다.
- 과다한 지역 변수를 사용하지 않도록 한다. 적절한 지역변수의 최대 갯수는 7개 정도라고 한다. 만약 지역 변수의 갯수가 많다면 함수를 좀 더 나눌 필요가 있다는 반증이 된다.
- global 변수의 이름은 최대한 의미를 지니도록 한다.
Comment
- 주석문은 /* */만을 사용한다. // 형식의 comment는 사용하지 않는다.
- Comment는 HOW가 아니라 What, Why를 중심으로 기술한다.
- 각 파일내에 정의되는 함수들에 대한 설명을 함수 정의 앞부분의 주석문으로 제공한다. 특히 외부로 Export 되는 함수에 대하여는 인자들에 대한 것과 리턴값, 그리고 함수 호출에 대한 가정등을 명세하도록 권장한다.
- 문장의 뒤쪽에 나타나는 주석문은 탭문자나 공백 문자를 이용하여 문장과 잘 구분이 되도록 하는 것이 좋으며, 여러 문장들의 끝에 위치하는 주석문들은 주석문 시작 위치를 정렬하여 가독성을 높이도록 한다.
- 파일의 앞 부분에 파일의 identity를 나타내는 헤딩 부분을 구성한다.
- 첫째줄은 "파일이름 - 간략한 설명"을 기술한다.
- 둘째줄은 author정보, 생성 날짜, 수정날짜,
- 그 뒤에는 file authoring과 관련된 주요 comment (필요한 경우)를 둔다.
- 그 다음은 RCS keyword substitution의 "$Log$"로 Check-in시마다 기록되는 로그항목이 기록될 수 있도록 한다.(이것은 쓰지 않기로, CVS에서 쓰이는 방식이며, diff시 불편)
- 공백라인을 삽입한 후 끝에 copyright notice 문구를 기술한다. 둘째줄의 날짜는, 파일 생성 날짜와, 그후의 주요 변경 날자를 나타내며, ',' 를 사용하여 적당히 축약하여 나타낸다.
/* cmdb_sysinfo.c - CMDB System Information Lookup Module *Clunix, Yongjae Lee <yjlee@clunix.com>, 2000.5.20,25,8.30. *From: glory's monitord/{cpuinfo.c, cpuload.c, diskinfo.c, *loadavg.c, meminfo.c, network.c, uptime.c, *version.c} at 2000.5.20. * *Copyright (c) 2000 by Clunix Inc. All Rights Reserved. */
C Header 파일
- 모든 C 헤더 파일의 구성은 다음과 같이 re-includable 할 수 있도록 한다.
...file heading... #ifndef _CM_H_ #define _CM_H_ ... includes ... ... defines and type definitions ... ... external interface definitons for file1.c ... ... external interface definitons for file2.c ... ... #endif /* CM_H */
- 화일 이름 cm.h라면 define symbol "_CM_H_" 의 관계에 주의하라.
- 화일 이름이 cmdb_proto.h 라면, symbol은 _CMDB_PROTO_H_ 가 된다.
- "defines and type definitions" 에서는, 가급적 매크로 상수 정의, type definitions, macro function의 나열하도록 한며 관련 사항들간에 grouping 될 수 있도록 한다.
- "... external interface definitons for ..." 에서는 해당 모듈에 대한 간단한 설명과, 해당 C파일의 이름이 들어있는 comment, 각 C 화일에서 export하는 symbol들을 변수, 함수 순으로 나열한다.
/* CMDB election and timeout; defined in "cmdb_ic.c" */ extern int cmdb_timeout_type; extern int cmdb_timeout_msec; /* in millisecond */ extern int cmdb_master_election_mode; #define CMDB_MASTER_ELECTION_NONE 0 #define CMDB_MASTER_ELECTION_SELF 1 #define CMDB_MASTER_ELECTION_OTHER 2 int cmdb_service_loop(void); int proc_cmdb_recv(int sock); int cmdb_recv_wait(int sock, int *timeout_msec); /* returns 0 on packet received or -1 on timeout or error */
- header file 내의 function prototype 선언에서, return 값의 의미가 자명하지 않은 경우 반드시, comment를 통해 return 값에 대한 설명을 기술한다.
- 외부로 export 되는 변수나 함수는 반드시 해당 header 파일을 통하여 extern prototype 선언이 있어야 한다. C 파일에서 header 파일 포함하여 prototype 선언이 compile시 check되도록 해야한다.
- 함수의 prototype 선언시 반드시 arguement type과 name이 정의되어야 한다.
struct list_item *get_list_item(list_item_t *list_tbl, int idx);