C언어 코드작성 포맷

Dingool95·2021년 6월 6일
0

C언어

목록 보기
1/5

들어가기

파이썬과 달리 C언어는 메인함수를 직접 작성해줘야 한다.
또한 들여쓰기가 문법에 속하지 않기 때문에
동일한 기능을 하는 코드임에도 개발자의 취향이나 습관에 따라 코드 작성법이 제각각이다.

하지만 개발자는 실력이 늘수록 협업할 일이 많고
협업은 서로 코드를 공유하고 리뷰하기도 한다.

따라서 가독성이 중요하다. 가독성을 높이기 위해서, 각 언어별로 권장되고 바람직한 코드 작성법이 존재하며, 주니어 개발자 때부터 이런 방식으로 습관을 들이면 나중에 고생하지 않을 수 있다.

스스로 작성한 코드도 시간이 지나면 잊어버린다. 그래서 가독성이 높은 코드는 꼭 협업을 하지 않고, 혼자서 볼 때에도 빠른 이해를 도울 수 있다.

'hello, world' 라는 아주 전통적인 문자열을 터미널 창에 출력해주는
간단한 예제 코드로, C언어 코드를 작성하는 다양한 방법을 알아보고
권장되는 방법을 정리해보자.

내가 직접 엮은 것은 아니고, C언어를 가르쳐주신 강사님의 수업내용을 정리한 것이다.


C언어 코드의 배경지식

#include 는 '전처리 지시자'라고 한다.
#include 외에도 많은 전처리 지시자들이 있다. 전처리 지시자는
컴파일 할 때 처리되기 때문에 코드 실행 시간에 영향을 미치지 않는다.
전처리 지시자는 문장 끝에 세미콜론(;)을 붙이지 않는다.

#include 는 헤더파일을 불러와서 '복사 붙여넣기' 해주는 전처리 지시자이다.
아래 코드들은 문자열을 출력하는 예제를 다루고 있으므로, stdio.h라는 헤더파일을 불러온다. 헤더파일은 콘솔게임의 게임팩과 같은 개념이다. 입출력이라는 게임을 하고싶으면 stdio.h라는 게임팩이 필요한 것이다. 헤더파일은 .h로 끝난다.
stdio는 'standard input output'의 줄임말이다.

C 프로그램은 main함수가 반드시 하나만 존재해야 한다.
main함수는 Entry point (진입점)으로, C 프로그램이 실행되면 가장 먼저 main함수를 찾는다.


아래 나열되는 코드 중 어떤 것도 에러가 발생하지 않으며,
'hello, world' 라는 문자열을 출력하는 동일한 기능을 한다.

1번

#include <stdio.h>
main() {
    printf("hello, world\n");
}

C언어는 함수의 입력값과 출력값의 type을 명시적으로 지정해줘야 한다.
출력값의 type은 함수 이름 앞에, 입력값은 함수 이름 뒤 소괄호 안에 써준다.

그런데 1번 방식의 경우 입출력 중 어떤 type도 지정하지 않았다.
출력 type은 써주지 않으면 'int' 가 생략된 것으로 본다.
입력 type은 비어있으면 unknown 이다. 모른다는 것은 입력이 없다는 것과 다르다.
입력 type이 비어있는 것은 절대 권장되지 않는다.

참고로 C++는 입력 type이 비어있는 것은 void, 즉 없는 것으로 본다.
C언어와의 차이점이다.

1번 코드는 main함수의 끝에서 흔히 볼 수 있는 return 이 없다.
종료 코드값을 쓰지 않겠다는 것을 의미한다.

C언어는 세미콜론 ; 이 문장이 끝났음을 의미한다.
항상 문장 끝에 ;을 써주어야 한다. 에러가 발생하는 단골 요인 중 하나다.



2번

#include <stdio.h>
int main(void)
{
    printf("hello, world\n");
    
    return 0;
}

2번이 가장 권장되는 방법이고, 앞으로 계속 사용할 방법이다.

1번과 달리 main함수의 시작을 알리는 중괄호{가 main함수를 정의하는 라인보다 한 줄 아래에 위치한다. 이건 취향차이에 해당한다.
나는 2번과 같은 방식을 사용한다.

printf 함수를 호출하고 있다. printf 함수의 마지막 f 는 format을 의미한다.
출력형식 (왼쪽, 오른쪽 정렬과 같은) 을 지정할 수 있다는 의미이다.

문자열은 항상 "문자열"과 같이 쌍따옴표로 묶는다.
쌍따옴표 내부의 \ (back slash) 문자는 'escape sequence'라고 한다.
문자열인 현재 상태를 벗어나서 특수한 기능 또는 문자를 가능하게 한다.
\n 은 줄바꿈 기능을 한다.

main 함수 마지막의 return 0;에서 0은 '결과값' 또는 '종료 코드값' 이라고 하는데
C 프로그램을 실행한 운영체제가 이 종료 코드값을 전달 받는다.

종료코드 값이

0 이면 : 프로그램이 제대로 실행되었음을 의미.

0 이 아니면 : 프로그램이 제대로 실행되지 않았음을 의미, 코드에 따라 어떤 문제인지                   구별할 수 있음.



3번

#include <stdio.h>
void main(void)
{
    printf("hello, world\n");
}

펌웨어에서 동작되는 코드에서 주로 볼 수 있는 스타일이다.

펌웨어는 무한루프로 동작되기 때문에 return 할 일이 없다.
또한 main 함수의 입력 및 출력이 필요없다.



4번

#include <stdio.h>
int main(void)
{
    printf("hello,");
    printf("world");
    printf("\n");
    
    return 0;
}

2번과 기본적으로 같은 형태이지만 printf함수를 세 번 호출했다.
함수호출에는 오버헤드가 있으므로 가능한 함수 호출 횟수를 줄이는 것이 좋다.
2번과 동일한 문자열 출력에 세 번의 함수 호출을 했으므로
이 방식은 권장되지 않는다.



5번

#include <stdio.h>
int main(void)
{
    printf("hello,"
    	   "world\n"
           );
    
    return 0;
}

출력할 문자열의 길이가 너무 길어서 쪼갤 필요가 있다면,
4번이 아니라 5번과 같은 방식을 택하는 것을 권장한다.

몇 줄로 쪼개든지 상관없지만 주의할 점은
각 줄의 문자열을 모두 쌍따옴표로 감싸줘야 한다.

문자열을 쪼개서 5번과 같은 형식으로 printf문을 작성할 때는
가독성을 위해서 printf함수의 닫는 괄호를 마지막 문자열보다
한 줄 아래에 쓰도록 하고, ;을 빼먹지 말자.



6번

#include <stdio.h>
int main(void)
{
    printf("%s\n", "hello, world");
    
    return 0;
}

6번은 형식 지정자를 사용해서 문자열을 출력한다.
문자열을 나타내는 쌍따옴표 내부의 %문자를 '형식 지정자'라고 한다.
출력할 변수의 type 및 출력 형태를 지정할 수 있다.

%s는 변수의 시작 주소를 받아 null문자가 나오기 전까지 출력한다.
일반적으로 문자열을 출력할 때 사용한다.

변수로 지정되지 않은 문자열을 단순히 출력만 할 것이라면
6번과 같이 굳이 형식지정자를 사용할 필요 없이 2번 처럼 쓰면 된다.



7번

#include <stdio.h>
int main(void)
{
    char *str = "hello, world";
    printf("%s\n", str);
    
    return 0;
}

8번

#include <stdio.h>
int main(void)
{
    char str[] = "hello, world";
    printf("%s\n", str);
    
    return 0;
}

7번과 8번은 묶어서 비교해야 한다.
둘 다 미리 지정된 문자열을 형식 지정자를 통해 출력한다.
다만 7번은 포인터로 받았고, 8번은 배열로 받았다.

포인터로 문자열을 받으면 문자열 상수를 포인터가 가리킨다.
str = "hi, world" 와 같이 수정이 가능하고
이 때, 기존의 "hello, world"라는 상수는 그대로 있고
새로운 상수 "hi, world"str이라는 포인터가 가리킨다.

따라서 문자열을 포인터로 받으면 얼마든지 수정이 가능하며
문자열 상수를 가리키므로 포인터를 제외한 추가적인 메모리 사용이 없다.

배열로 문자열을 저장하면, str = "hi, world"와 같이 수정이 불가능하다.
strcpy(str, "hi, world")와 같이 문자열을 다루는 함수를 사용해야 한다.
또한 기존의 문자열 길이보다 더 긴 문자열로 수정하게 되면 기존의 메모리 공간을 초과하므로, 초과한 공간에 다른 내용이 저장되어 있는지에 따라 데이터 손실이 발생할 수 있다.
뿐만 아니라 배열은 추가적인 메모리를 필요로 한다.

문자열을 포인터 또는 배열로 저장한다는 것은 수정을 염두에 두고 있음을 말한다.
따라서 문자열을 저장할 때는 포인터로 받아서 7번과 같은 방식을 사용하는 것이 바람직하다.

C언어에서는 다른 언어와 달리, 문자열을 다루는 type이 따로 없다.
그래서 문자열을 배열 또는 포인터로 다루게 되는데
앞으로는 C언어에서 문자열의 type을 char *로,
문자열 상수는 const char *로 기억하자.



9번

#include <stdio.h>
int main(void)
{
    fprintf(stdout, "hello, world\n");
    
    return 0;
}

나는 MATLAB 에서는 출력할 때 거의 fprintf 함수만을 사용한다.
C언어에서는 아직 잘 써지지 않는 함수이다.

fprintf의 첫 f는 file을 의미한다. 표준 출력파일이 fprintf라고 한다.
그리고 stdout은 표준 출력장치, 즉 모니터를 의미한다.

UNIX 운영체제에서는 모든 장치를 file로 다룬다고 한다.
C언어 역시 UNIX를 모태로 하고 있기 때문에 이를 사용하는 것 같다.

솔직히 file로 다룬다는 것이 어떤 의미인지 잘 모르겠고,
fprintf를 써야만 하는 경우도 아직 마주치지 않았다.

나중에 공부를 더해서 필요에 의해 printf와 더불어 선택할 수 있어야 겠다.

profile
내 맘대로 요점정리

0개의 댓글