[CS50] 3-0. Prequel

(1) 컴파일(Compile)

세 번째 강의의 원 제목은 '배열(array)'지만, 들어가기 전 프로그램 생성 및 실행에 대한 간단한 로직 설명이 있어 먼저 정리하려고 한다.

모든 프로그램의 구동 방식인 컴파일(Compile)을 언급하기 전에 기본적인 C언어 코드를 분석해보자.

#include <stdio.h>

int main(void)
{
    printf("hello world\n");
}

#include <stdio.h>는 헤더파일로, 메인에서 실행하는 함수가 무엇인지 알려주는 역할을 한다. .h 확장자를 가지고 있다. int main(void){}는 주요 기능이 담긴 영역이다. printf()는 출력 함수인데, <stdio.h>에 들어 있다.

이는 컴퓨터에게 컴파일 절차를 알려준다. clang 혹은 make 등의 컴파일 절차를 실행하면 먼저 ①preprocessing에 들어가 헤더파일, 메인 영역, 기능 등을 읽는다. 그 후 ②compiling하여 어셈블리어(저급 수준 프로그래밍 언어)로 번역한다. 번역된 코드는 다시 ③assembling 작업에 들어가 기계어로 재번역한다. 여기서 우리의 코드는 0과 1의 조합이 된다. 마지막으로 ④linking하여 각각의 기계어 (헤더파일, 메인 영역, 기능)를 연결해 하나의 실행 프로그램으로 만든다. 이 과정을 줄여서 보통 compiling이라고 부른다.


(2) 디버깅(Debuging)

프로그래밍 상에서 버그(bug)코드 상의 오류를 뜻하며, 디버그(debug)는 해당 오류를 검사 및 수정하는 과정을 가리킨다. 이 단어들의 뜻은 유명한 컴퓨터 과학자인 Grace Hopper가 'Mark2'라는 컴퓨터 시스템을 개발하는 동안 '진짜 벌레(bug)'가 들어가 오류를 발생시킨 것에서 유래되었다.

버그는 여러 이유로 발생할 수 있는데, 크게 2가지로 볼 수 있다. 문법상 또는 기능상의 오류인 코드 오류와 기능적으로는 잘 돌아가지만 원하는 결과가 나오지 않는 논리적 오류이다. 전자는 컴퓨터가 에러 메세지를 띄워주므로 쉽게 알 수 있다.

후자는 상황에 따라 다르다. 코드가 단순할 때는 찾기가 쉽겠지만, 복잡하다면 눈알이 빠질 위기에 처하거나 모니터를 부수고 싶은 충동에 휩싸인다. 이럴 때 확인할 수 있는 단순한 방법은 의심되는 기능 주위에 출럭 함수를 난사하는 것이다. 예를 들면, 아래 코드처럼 할 수 있다.

#include <stdio.h>

int main(void) 
{   
   for (int i = 2; i <= 10; i++)
        printf("i = %i", i) // debuging 함수
   {
       for (int j = 1; j <= 9; j++)
       {
           printf("j = %i", j) // debuging 함수
           printf("%i * %i = %i\n", i, j, i * j);
       }
       printf("\n");
   }
}

2단부터 9단까지 출력하는 것이 목적이었지만, 해당 코드는 10단까지 출력한다. 이때 사이사이 끼워놓은 출력 함수를 보고 어디가 원인인지 파악할 수 있다. 찾고 나면 버그 코드를 고치고 디버깅 함수를 지우면 된다. 그러나 매우 불편한 방법임이다. 복잡하고 많은 양의 코드라면 이것이 얼마나 귀찮겠는가. 이럴 때 세상이 좋아짐에 만세를 부르게 된다. 우리가 보통 코딩할 때 사용하는 툴, IDE(Integrated Development Environment, 통합 개발 환경)에서 Debuging을 제공한다.

빨간색 정지 버튼 같은 점은 Break Point(중지점)로 상위 코드가 쭉 실행되다 저기서 멈춘 후 한 단계씩 로직이 어떻게 실행되는지 확인할 수 있다. 굳이 출력 코드를 썼다 지웠다할 필요가 없다.


(3) 코드의 디자인

코드 작성만큼 테스트도 중요한데, 이유는 버그 발생을 최소화하고 내가 원하는 결괏값을 얻기 위해서이다. 그 과정에서 코드 몇 줄로 해결될 일을 수십 줄로 늘려 메모리를 낭비할 필요는 없으니까.

스타일 측면도 중요하다. 바로 가독성을 의미하는데, 그래야 협업이나 유지보수에 용이하기 때문이다.

#include <cs50.h>
#include <stdio.h>

int main(void){int n = get_int("n: ");if (n % 2 == 1){printf("odd\n");}else{printf("even\n");}}

입력값의 홀수와 짝수를 구분하는 간단한 코드지만, 한 줄로 적어 놓으니 눈이 불편하다. 실행에는 문제가 없지만, 다음에 코드를 고치거나 참고할 때 눈에 확 들어오지 않는다. 유지보수의 편의성과 직관성, 나아가 내 눈의 피로도까지 감안한다면 코드를 정리하여 가독성을 높이는 편이 나을 것이다.

#include <cs50.h>
#include <stdio.h>

int main(void)
{
	int n = get_int("n: ");
    if (n % 2 == 1)
    {
    	printf("odd\n");
    }
    else
    {
    	printf("even\n");
    }
}

눈도 속도 편안하다. 개행이나 들여쓰기를 습관화하자.

좋은 웹페이지 즐겨찾기