2011. 9. 14. 17:25

[ 041 ] - #define 문을 사용하여 소스 코드에서 사용하는 상수들을 미리 정의하자.

C 언어에서 사용하는 #define 문은 사무실에 놓여 있는 꽃병이나 화분처럼

그저 보는 데 만족하라고 있는 기능이 아닙니다.

고수 프로그래머들의 소스 코드를 보면 여러 가지 #define 문을 사용하여 굳이 소스 코드에 대한 주석을 보지 않고도

이 소스 코드의 기능이 무엇인지 알 수 있을 정도입니다. 대부분의 초보 프로그래머들이 귀찮거나 번거롭다고 해서

#define 문을 사용을 주저하는 경우가 많은데 #define 문을 사용하지 않고 0과 1로 도배하다시피

한 소스 코드는 한두 달 지나면 소스 코드를 만든 프로그래머조차 쉽게 이해하지 못할 만큼 어려운 코드가 됩니다.

 

[ 042 ] - 포인터는 선언하자마자 초기화하자.

포인터는 C 언어에서 최고로 강력한 기능입니다. 하지만 이와 같이 강력한 기능을 제대로 사용하지 않으면

여러 가지로 어려운 일이 생길 수 있으므로 일단 포인터를 사용하면 반드시 초기화하는 습관을 갖는 것이 좋습니다.

 

[ 043 ] - 논리적인 버그가 생길 수 있는 부분에 검사 코드를 넣어 두자.

초보 프로그래머들이 오해하는 것 가운데 하나는 컴파일러가 만능이라고 착각하는 것입니다.

컴파일러에서 특별한 에러나 경고 표시가 없으면 그 프로그램은 전혀 문제가 없을 것이라고 생각하지만

프로그램은 그것을 개발한 프로그래머의 의도대로만 실행되지는 않습니다.

대부분의 프로그래밍의 고수들은 말도 안 되는 상황을 많이 경험했기 때문에 고수들은 혹시라도 문제가

생길 수 있는 부분을 철저하게 검사하도록 코드를 구현합니다.

물론 너무 많은 검사 코드가 프로그램의 원래 기능을 방해해서는 안 되겠지만,

만에 하나 일어날 수도 있는 버그를 미리 막을 수 있도록 프로그램에 검사 코드를 추가하는 습관을 들이는 게 중요합니다.

 

[ 044 ] - 메모리의 할당과 해제를 할 때에는 별도의 함수를 사용하자.

C 언어가 메모리에 너그러운 프로그래밍 언어이기 때문에 프로그램 안에서 메모리를 사용할 때도

malloc() 함수와 free() 함수만 사용해 주면 특별한 문제는 없습니다.

하지만 malloc() 함수와 free() 함수만 사용하기에는 C 언어의 지나친 너그러움이 오히려 장애가 될 수 있습니다.

대부분의 프로그래밍 고수들은 malloc() 함수와 free() 함수를 직접 불러서 사용하지 않고 별도의 메모리 할당과 해제를

위한 함수를 만들어서 사용합니다. 이와 같은 함수를 래퍼 함수(wrapper function)라고 하는데 래퍼 함수를 사용하면

메모리를 사용할 때 생길 수도 있는 버그를 대부분 미리 막을 수 있습니다.

본문에서 다룬 malloc() 함수와 free() 함수에 대한 래퍼 함수들을 잘 살펴보고

여러분만의 래퍼 함수를 만드는 습관을 들이세요.

 

[ 045 ] - 하나 이상의 반환 값이 필요할 때는 포인터를 사용하자.

지금까지 C 언어에서 함수는 오직 하나의 반환 값만을 처리할 수 있다고 귀에 못이 박히도록 배웠을 것입니다.

하지만 실무에서 프로그래밍을 하다 보면 두 개 이상의 반환 값이 필요한 경우가 있습니다.

특히 함수의 정상적인 실행 여부를 확인하기 위해서는 반환 값이 필수인데, 바로 이때 포인터를 매개변수로 사용하면

실제 반환 값처럼 사용할 수 있습니다. 이와 같은 방법은 고수들이 자주 사용하는 방법 가운데 하나이며

프로그램의 버그를 막기에도 더할 나위 없이 좋은 프로그래밍 습관입니다.

 

[ 046 ] - 포인터가 가리키는 값을 증가시킬 때에는 반드시 괄호를 사용하자.

종종 어떤 프로그래머들은 포인터가 가리키는 값을 증가시키는 코드를 다음과 같이 만듭니다.

*pNum++;

하지만 위의 코드를 실행해 보면 포인터가 가리키는 데이터의 값이 1씩 증가하는 것이 아니라

포인터 자체의 주소 값이 1씩 증가하는 것을 알 수 있습니다.

사실 이와 같은 버그는 찾기도 어렵지만 프로그래머가 예상하지 못한 곳으로 포인터가 이동하기 때문에

나중에 심각한 문제를 일으킬 수 있습니다.

따라서 포인터가 가리키는 값을 증가시키기 위해서 반드시 괄호를 사용해야 합니다.

(*pNum)++;

괄호를 사용하는 것 하나만으로도 최소한 포인터를 잘못 사용해서 일어나는 문제의 대부분을 줄일 수 있습니다.

 

 

[ 047 ] - malloc()과 free() 함수를 정확하게 구분해서 사용하자.

프로그램에서 흔히 지나치기 쉬운 기능 가운데 하나가 malloc()과 free() 함수입니다.

malloc() 함수는 동적으로 메모리를 할당하며 반대로 free() 함수는 할당받은 메모리를 해제하는 역할을 합니다.

이 장에서는 malloc()과 free() 함수를 사용할 때 일어날 수 있는 몇 가지 문제들을 살펴봤습니다.

여기에서 다룬 문제는 예상되는 문제들 가운데 간단한 것들이며 그 밖에도 많은 문제들이 도사리고 있습니다.

malloc()과 free()를 사용할 때 일어나는문제들을 막기 위해서는 malloc()과 free() 함수를 사용할 때마다

주의 깊게 살펴봐야 하며 그러한 문제들을 예상해서 미리 그에 대한 대비 코드를 작성해두어야 합니다.

 

[ 048 ] - 모든 자료형을 복사할 때는 memcpy() 함수를 사용하자.

초보 프로그래머들이 가장 많이 사용하는 복사 함수는 strcpy() 함수입니다.

strcpy() 함수는 문자열을 복사하기 위해 만들어진 함수이기 때문에 구조체나 다른 자료형을 복사하기는 어렵죠.

이와 같은 경우에 대부분의 초보 프로그래머들은 특정한 자료형을 복사하기 위해

자신이 직접 함수를 만들어서 사용하곤 합니다. 하지만 이때 요긴하게 사용할 수 있는 함수가 memcpy()입니다.

한 번만 memcpy() 함수의 사용법을 익혀 두면 프로그래밍을 할 때 의외로 편할 때가 많으므로 꼭 기억해 두세요.

 

[ 049 ] - 초기화를 할 때는 memset() 함수를 사용하자.

어떤 데이터든지 만든 후에는 초기화하는 습관을 갖는 것이 좋습니다.

하지만 천차만별인 자료형에 맞게 초기화를 하기란 쉽지 않은 일이죠.

이와 같은 경우에 memset() 함수를 사용하면 쉽게 초기화를 할 수 있습니다.

특히 초보 프로그래머들은 배열을 초기화할 때 for 문을 사용하는 경우가 많은데

이때야말로 memset() 함수를 사용하는 것이 좋습니다.

 

[ 050 ] - 함수 포인터를 사용하자.

함수 포인터를 사용하면 프로그램의 유지 보수가 한결 간편해집니다.

이와 같은 함수 포인터의 장점 때문에 커널이나 임베디드 프로그램과 같이

최적화와 유지 보수성이 좋아야 하는 프로그램 코드에서는 함수 포인터를 자주 사용합니다.

하지만 함수 포인터를 정확하게 이해하지 못하면 코드를 이해할 수 없을뿐더러 수정하기가 여간 어렵지 않으므로

필요한 때 함수 포인터를 사용할 수 있도록 개념을 이해하고 사용 방법을 익혀 두세요.

Posted by devanix