C 코딩 스타일 가이드 - 서식
- 소프트웨어 개발 및 프로젝트 관리/코딩 규칙
- 2019. 2. 24.
본 문서는 소프트웨어 개발 시 준수해야 하는 코딩 스타일을 정의하고 가이드한다.
본 문서의 가이드는 C 언어를 대상으로 하고 있으며 C99 표준이 적용된다(추후 C11 등 최신 표준으로 변경 적용 가능하며, 이에 따라 본 문서의 내용이 일부 변경될 수 있다).
본 문서의 가이드는 구글 C++ 코딩 스타일 가이드(https://google.github.io/styleguide/cppguide.html)를 기반으로 내부적인 필요에 따라 일부 내용을 수정, 변경하여 적용한 것이다.
참고로 본 스타일 가이드에 기술된 대부분의 가이드 항목은 IDE나 편집기에 설정하여 자동 적용되도록 할 수 있다.
서식
코딩 시 모두가 통일된 스타일을 사용하면 프로젝트를 파악하기 쉬워진다.
각자가 모든 서식 규칙에 동의하기 어렵고, 일부는 익숙해지는데 시간이 걸리지만, 프로젝트 구성원들이 규칙에 따라 코드를 작성함으로써 서로의 코드를 쉽게 이해하도록 하는 것은 중요하다.
줄 길이
F-1. 코드의 각 줄은 120 문자를 넘지 않게 한다.
문자 형식
F-2. 문자는 되도록 ASCII 문자를 사용하고, ASCII가 아닌 문자를 사용할 경우에는 UTF-8 형식을 사용한다.
들여쓰기
F-3. 단계 당 2개의 스페이스로 들여쓰기(indentation) 하고 탭은 사용하지 않는다.
또한 코드 상의 그 어디에서도 탭을 사용하지 않는다.
중괄호
F-4. 중괄호로 묶이는 모든 코드 블럭에서, 각 중괄호 "{", "}" 는 구문에 따라 같은 줄에 작성하거나 줄바꿈하여 작성한다.
// 함수 내용을 여는 중괄호와 닫는 중괄호는 모두 새로운 줄에 작성한다.
int Function(int a)
{
}
// 구조체 내용을 여는 중괄호와 닫는 중괄호는 모두 새로운 줄에 작성한다.
struct Structure
{
};
// 열거형 내용을 여는 중괄호와 닫는 중괄호는 모두 새로운 줄에 작성한다.
enum eCode
{
};
// 조건문 내용을 묶는 중괄호는 같은 줄에 작성하고, 닫는 중괄호는 새로운 줄에 작성한다.
// 단, 가독성이 현저하게 낮은 경우 가독성 향상을 위해 묶는 중괄호를 새로운 줄에 작성할 수도 있다.
if (condition) {
DoSomething();
}
// switch 문을 묶는 중괄호는 같은 줄에 작성하고, 닫는 중괄호는 새로운 줄에 작성한다.
// 단, 가독성이 현저하게 낮은 경우 가독성 향상을 위해 묶는 중괄호를 새로운 줄에 작성할 수도 있다.
switch (var) {
case 0:
...
}
F-5. 모든 조건문(if, switch)과 반복문(for, while)에서 중괄호를 반드시 사용한다. 본문이 한 줄인 경우에도 중괄호를 사용한다.
if (condition) {
DoSomething();
}
while (condition) {
DoSomething();
}
switch (var) {
case 0:
...
}
강제 줄 바꿈
F-6. 모든 조건문(if, switch), 반복문(for, while)의 표현식이 정해진 가로 줄 길이를 초과할 경우, 가독성 좋게 정렬하여 줄바꿈한다.
1) 일관성 있게 줄바꿈 한다.
2) 각 줄의 시작지점을 통일한다.
3) 보통 연산자 뒤에서 줄바꿈한다.
if ((this_one_thing > this_other_thing) &&
(a_third_thing == a_fourth_thing) &&
yet_another &&
last_one) {
..
}
함수 선언과 정의
F-7. 기본적으로 리턴 타입과 함수이름, 인자를 같은 줄에 작성하지만, 정해진 가로 줄 길이를 초과할 경우 줄바꿈하여 작성할 수 있다.
// 기본 형식
ReturnType FunctionName(Type var1, Type var2)
{
DoSomethong();
}
// 한줄에 작성하지 못할 경우, 리턴 타입 작성 후 줄바꿈하여 작성한다.
ReturnType
ReallyLongFunctionName(Type var1, Type var2, Type var3)
{
DoSomething();
}
// 리턴 타입을 제외한 함수이름, 인자만으로도 한줄에 작성하지 못할 경우, 리턴타입과 함수이름을 한줄에 작성하고, 각 인자를 서로 다른 줄에 작셩한다.
ReturnType ReallyLongLongLongLongLongFunctionName(
Type var1,
Type var2,
Type var3)
{
DoSomething();
}
주의 사항
- 여는 괄호 "(" 는 항상 함수 이름과 같은 줄에 작성한다.
- 닫는 괄호 ")" 는 항상 마지막 인자에 붙여서 작성한다.
- 함수 이름과 여는 괄호 "(" 사이에는 스페이스를 넣지 않는다.
- 여는 괄호 "(" 및 닫는 괄호 ")" 와 인자 사이에는 스페이스를 넣지 않는다.
- 각 인자 사이는 쉼표 + 하나의 스페이스를 사용하여 구분한다.
- 여는 중괄호 "{" 는 항상 닫는 괄호 ")" 다음 줄에 작성한다.
- 닫는 중괄호 "}" 는 혼자 마지막 줄에 위치해야 한다.
- 모든 인자는 이름을 가져야 하며, 선언과 구현에서 같은 이름을 가져야 한다.
- 함수 내 기본 들여쓰기는 2개의 스페이스이다.
- 모든 인자들은 가능한 한 정렬되어야 한다.
- 인자들이 다음 줄로 이동할 경우 2개의 스페이스 들여쓰기를 사용한다.
- 인자들이 다음 줄로 이동할 경우 한 줄당 하나의 인자만 작성한다.
함수 호출
F-8. 기본적으로 한 줄로 작성하지만, 정해진 가로 줄 길이를 초과할 경우 줄바꿈하여 작성할 수 있다.
// 기본 형식
bool retval = FunctionName(argument1, argument2, argument3);
// 같은 줄에 작성하지 못하는 경우, 첫번째 인자를 제외한 나머지 인자들을 별도의 줄에 작성한다.
// 인자의 시작위치는 통일한다.
bool retval = ReallyLongLongLongLongLongFunctionName(argument1,
argument2,
argument3);
주의 사항
- 여는 괄호는 항상 함수 이름과 같은 줄에 작성한다.
- 닫는 괄호는 항상 마지막 인자에 붙여서 작성한다.
- 함수 이름과 여는 괄호 사이에는 스페이스를 넣지 않는다.
- 괄호와 인자 사이에는 스페이스를 넣지 않는다.
- 각 인자 사이에는 스페이스를 사용한다.
- 모든 인자들은 가능한 한 정렬되어야 한다.
- 인자들이 다음 줄로 이동할 경우 한 줄당 하나의 인자를 작성한다.
switch 문
F-9. case 구문은 스페이스 2개로 들여쓰기 한다.
F-10. case 구문의 본문은 스페이스 4개로 들여쓰기 한다.
F-11. 항상 default 구문을 포함해야 한다. default 케이스가 실행되지 말아야 할 경우 assert()하거나 사용자가 알 수 있도록 로그 출력 등을 수행해야 한다.
switch (var) {
case 0:
..
break;
case 1:
...
break;
default:
assert(false);
}
반복문
F-12. 비어 있는 반복문은 세미콜론 ";" 대신 중괄호 "{}" 를 사용하고, 중괄호는 조건문 다음에 붙여서 작성한다.
for (int i = 0; i < kSomeNumber; ++i) {}
while (condition); // 나쁨
while (condition) {} // 좋음
리턴값
F-13. return 표현식을 불필요하게 괄호로 묶지 않는다.
return result; // 좋음 - 괄호 사용이 필요 없는 간단한 경우
return (some_long_condition && // 좋음 - 복잡한 표현식의 가독성을 높이는 경우 괄호가 허용됨.
another_condition);
return (value); // 나쁨
return(result); // 나쁨
전처리기 지시자
F-14. 전처리기 지시자의 "#" 기호는 항상 그 줄의 처음에 작성한다. (들여쓰기 된 코드의 내부의 전처리기 지시자 포함)
// 좋음 - 지시자가 줄의 처음부터 시작한다.
#define NORMAL
if (lopsided_score) {
#if DISASTER_PENDING // 좋음
DropEverything();
#if NOTIFY // 좋음
NotifyClient();
#endif
#endif
BackToNormal();
}
// 나쁨 - 지시자가 들여쓰기 되어 있다.
if (lopsided_score) {
#if DISASTER_PENDING // 나쁨
DropEverything();
#endif // 나쁨
BackToNormal();
}
F-15. 전처리기 지시자가 코드 블럭을 감싸고 있는 경우, 닫는 부분 "#endif" 뒤에는 여는 부분에 명시된 조건을 주석으로 표기한다.
if (lopsided_score) {
#if DISASTER_PENDING
DropEverything();
#if NOTIFY
NotifyClient();
#endif // NOTIFY
#endif // DISASTER_PENDING
BackToNormal();
}
가로 공백
F-16. 줄 끝에는 공백 문자를 사용하지 않는다.
줄 끝에 공백 문자를 두면 같은 파일을 편집하는 다른 사람이 기존의 뒤쪽 공백 문자를 삭제할 경우, 코드 내용의 변경이 없이도 코드 변경이 발생한다.
가로 공백 - 일반 사항
int i, j;
int x[] = { 0, 1, 2};
int i = 0; // 모든 문장의 세미콜론 앞에는 스페이스를 사용하지 않는다.
switch (i) {
case 3: // switch 문의 case 구문의 콜론 앞에는 스페이스를 사용하지 않는다.
...
}
out: // goto 문에서 사용되는 분기구문의 콜론 앞에는 스페이스를 사용하지 않는다.
...
F-19. 각 괄호 "(", ")" 와 괄호 안 내용 사이에는 스페이스를 넣지 않는다. 괄호 안 내용 자체는 가독성을 위해 스페이스를 사용할 수 있다.
int ret = Function(a, b);
int result = 1 + (a + b);
for (int i = 0; i < 5; ++i)
F-20. 중괄호 "{", "}" 를 이용한 리스트 초기화 시, 중괄호와 괄호 안 내용 사이에는 하나의 스페이스를 넣는다. 괄호 안 내용 자체도 가독성을 위해 스페이스를 사용할 수 있다.
int x[] = { 0, 1, 2 };
가로 공백 - 반복문과 조건문 (if, else if, for, while)
// 좋음
if (condition)
switch (var)
while (condition)
// 나쁨
if(condition)
switch(var)
while(condition)
F-22. 조건문/반복문에서 각 괄호 "(", ")" 와 조건구문/반복구문 사이에는 스페이스를 넣지 않는다.
switch (var) // 좋음
switch ( var ) // 나쁨
for (int i = 0; i < 5; ++i)
for (; i < 5; ++i)
가로 공백 - 연산자
하지만 가독성을 위해서 각 항 마다 스페이스를 넣지 않을 수도 있다.
a = (w * y) + (t / z) - 1;
a += 3;
a = b >> 3;
a = b ^ 2;
a = y | 3;
a = z & 3;
a = (w*y) + (t+z); // 가독성을 위해 스페이스 생략 가능
F-25. 단항 연산자(예: -, ++, !) 와 그 인자 사이에는 스페이스를 넣지 않는다.
x = -5;
++x;
if (x && !y)
세로 공백
F-26. 세로 공백의 사용을 최소화한다.
꼭 필요한 경우가 아니면 빈 줄을 사용하지 않는다. 더 많은 코드가 화면에 들어올수록 프로그램의 흐름을 따라가거나 이해하기 쉽다.
단, 지나치게 조밀한 코드는 가독성을 저해하므로 적절한 수준을 유지해야 한다.
F-27. 함수 사이에 3개 이상의 빈 줄을 추가하지 않는다.
F-28. 함수의 시작이나 끝 부분에 빈 줄을 사용하지 않는다.
F-29. 함수 내부에서도 빈 줄을 되도록 사용하지 않는다.
단, 가독성 향상을 위해 블록 별로 빈 줄로 구분할 수 있다.
if 문
F-30. else if 또는 else 문은 이전 if 문 또는 else if 문을 닫는 중괄호와 같은 줄에 작성한다.
필요한 경우, 가독성을 위해 이전 중괄호의 다음 줄에 작성할 수도 있다.
// 기본 형식
if (condition) {
} else if (condition) {
} else {
}
// 가독성을 위해 허용 가능한 형식
if (condition) {
}
// 주석….
else if (condition) {
}
// 주석 …
else {
}
기타
상식적이고 일관성있게 작성한다.
코드를 수정하는 경우 잠시 주변의 코드를 살펴 그것의 스타일을 판단하고, 해당 코드와 일관성을 가지도록 작성한다.
이 스타일 가이드를 따르지 않는 기존 코드와의 일관성을 유지하기 위해 본 가이드라인을 따르지 않을 수 있다.
파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
'소프트웨어 개발 및 프로젝트 관리 > 코딩 규칙' 카테고리의 다른 글
C 코딩 스타일 가이드 - 함수 (0) | 2019.03.21 |
---|---|
C 코딩 스타일 가이드 - 주석 (0) | 2019.03.20 |
C 코딩 스타일 가이드 - 변수 범위 (0) | 2019.03.17 |
C 코딩 스타일 가이드 - 이름 규칙 (0) | 2019.03.14 |
C 코딩 스타일 가이드 - 헤더파일 (0) | 2019.02.20 |