2011. 9. 14. 16:47

[ 021 ] - 함수의 매개변수를 사용하여 연산하지 말자.

초보 프로그래머들의 실수 가운데 하나는 함수의 매개변수를 for 문이나 while 문의 제어 조건을 이용한다는 것입니다.

하지만 고수 프로그래머들은 매개변수를 사용하여 함수 내부의 연산을 하지 않습니다.

매개변수의 값을 연산할 필요가 있다면, 함수 내부에 별도의 변수를 하나 선언해서 그 변수에 매개변수의 값을 받아 연산을

하는 것이 바람직합니다.

매개변수로 연산을 하지 않는 것은 디버깅 시간을 줄여주며 매개변수 때문에 일어날 수도 있는

논리적인 오류를 미리 예방할 수 있습니다.

 

[ 022 ] - 함수의 매개변수를 검사하자.

함수가 호출되면 고수 프로그램의 코드는 함수에서 사용하는 매개변수의 값을 검사합니다.

매개변수의 값이 정상적인 값인지 먼저 확인하고 나서 실제 함수 내부의 코드를 실행하는 것이죠.

이와 같은 과정은 특히 포인터를 매개변수로 사용할 때 치명적인 메모리 에러를 예방할 수 있습니다.

여러분도 포인터를 매개변수로 사용할 때 잊지 말고 검사 코드를 추가하기 바랍니다.

 

[ 023 ] - 함수의 반환 값을 이용하여 함수의 실행 여부를 판단하자.

초보 프로그래머들은 함수의 반환 값을 단지 함수의 연산 결과를 저장하는 용도로만 사용하지만,

프로그래밍 고수들은 함수의 반환 값을 사용하여 호출한 함수가 정상적으로 실행되었는지

아니면 중간에 어떤 오류가 있었는지 판단합니다.

물론 모든 함수의 반환 값을 함수의 실행 여부를 판단하는 용도로 사용할 수는 없지만,

함수의 실행 여부가 전체 프로그램에서 중요한 역할을 한다면 함수의 반환값을 사용하여

함수의 실행 여부를 판단하는 습관을 들이세요.

 

[ 024 ] - printf("[%s] [%s] [%d]\n", _FILE_, _FUNCTION_, _LINE_);을 적극적으로 활용하자.

프로그램의 코드가 길어지고 논리적으로도 복잡해지면 디버깅을 하기가 좀처럼 쉽지 않습니다.

요즘 사용하는 비주얼 C++와 같은 개발 도구는 디버깅을 쉽게 할 수 있는 기능이 갖추어져 있지만,

모든 개발을 비주얼 C++만으로 할 수는 없기 때문에 개발 환경이 윈도우, 리눅스에 상관없이

다음과 같은 코드를 사용해서 디버깅을 좀더 쉽고 효율적으로 할 수 있습니다.

printf("[%s] [%s] [%d]\n", _FILE_, _FUNCTION_, _LINE_);

위의 코드가 갖는 의미는 현재 위치에서 사용하는 파일의 이름과 함수의 이름, 그리고 소스 코드의 행 번호를

화면에 출력하라는 의미입니다.

예를 들면 본문의 예제처럼 프로그램의 실행을 어떤 오류 때문에 중지해야 할 경우 어느 모듈의 어느 부분에서

중단되었는지 알기 어렵기 때문에 프로그램의 실행을 중단해야 하는 코드에 위의 코드를 넣어주면

아래 결과 화면에서 현재 어떤 위치에서 실행을 중단했는지 쉽게 알 수 있습니다.

[f:\test1\main.c][main][23]

위의 결과는 현재 코드 위치가 main.c 소스 파일의 main 함수에서 23행이라는 의미입니다.

 

[ 025 ] - 초보 프로그래머들의 실수 열 가지를 피하자.

초보 프로그래머들은 아직 프로그래밍 경험이 많지 않기 때문에 자신이 만든 프로그램이 특별한 에러 없이 실행 파일이

만들어진다는 것만으로도 감격해 합니다. 하지만 실행 파일은 컴파일이 되는 정도를 나타내 줄 뿐이고 프로그램이

정상적으로 실행될 것이라는 보장을 해 줄 수는 없습니다.

 

초보 프로그래머들이 흔히 저지르기 쉬운 실수 가운데 아래와 같이 컴파일러에서 에러로 표시하지 않는 열 가지.

① 함수의 매개변수의 이름이 같은 경우

② 함수의 반환 값과 반환 값을 저장하는 변수의 자료형이 다른 경우

③ 제어변수의 연산을 제대로 하지 않는 경우

④ 변수의 이름이 a, b, c나 i, j, k처럼 의미 없는 경우

⑤ 음수 값을 가질 수 없음에도 음수 검사를 하는 경우

⑥ 포인터를 초기화하지 않고 사용하는 경우

⑦ 배열의 크기나 malloc()의 크기를 임의로 잡는 경우

⑧ if-else 문의 괄호를 제대로 설정하지 않는 경우

⑨ 0과 1의 설정이 잘못된 경우

⑩ == 연산자 대신 = 연산자를 사용한 경우

 

[ 026 ] - 삼항 연산자를 적극 활용하자.

삼항 연산자를 리눅스 관련 프로그램 코드에서 쉽게 볼 수 있는 연산자이며 프로그래밍의 고수라고 하는 사람들의

소스 코드에서도 쉽게 볼 수 있는 연산자입니다.

삼항 연산자는 여러 줄로 구현하는 if~else 문을 한 줄로 줄여서 표현하는 효과도 있지만, if~else 문으로 구성된 코드보다

훨씬 더 빠르게 소스 코드를 이해할 수 있도록 도와줍니다.

삼항 연산자의 사용법을 조금만 익히면 프로그래밍에 많은 도움이 될 것입니다.

 

일반적인 예:

max = (a > b) ? a : b;

 

 

[ 027 ] - 연산자의 우선순위를 항상 고려하자.

대부분의 프로그래밍 책에서 언급하는 연산자의 우선순위를 가볍게 생각하는 프로그래머가 많습니다.

특히 초보 프로그래머들은 포인터나 구조체 등의 고급 기능을 이해하는 데에는 많은 주의를 기울이지만 연산자 우선순위에

대한 내용은 마치 사칙연산(+, -, *, /)정도의 수준에서 이해하는 경우가 많습니다.

오히려 포인터나 구조체, 메모리에 관련된 고급 기술은 시간이 지나면서 실무를 통해 자연스럽게 익힐 기회가 있지만

연산자 우선순위는 기억해 두고 있지 않으면 사용할 수 없기 때문에 영어 단어를 암기하듯이 항상 외워두어야 합니다.

 

다음은 꼭 기억해두어야 할 우선순위를 나열한 표입니다.

우선순위

연산자 종류

연산자

높음

낮음

괄호∙배열∙구조체 연산자

() [] -> .

단항 연산자

! ~ ++ -- (형 변환 연산자) * & sizeof

곱셈, 나눗셈 연산자

* / %

덧셈, 뺄셈 연산자

+ -

시프트 연산자

<< >>

비교 연산자

< <= > >=

비교 연산자

== !=

비트 연산자

& ^ |

논리 연산자

&& ||

삼항 연산자

? :

대입 연산자

= += =+ *= /= &=

대입 연산자

> >= < <= &= ^= |=

 

 

[ 028 ] - x++와 ++x의 차이를 정확하게 알자.

고수라고 인정받는 개발자들도 x++와 ++x의 차이를 명확하게 알지 못하는 경우가 많습니다.

++ 연산자가 단순히 증감 연산자라는 정도는 알지만 x++와 ++x가 완전히 다른 결과를 가져다 준다는 사실은 잘 모릅니다.

작은 표현의 차이지만 결과의 차이는 큰 증감 연산자의 사용에 대해서 확실하게 이해합시다.

 

다음 코드를 직접 입력해서 실행해 보세요.

위의 코드를 실행한 결과는 다음과 같습니다.

z : 1 x : 2

z : 2 y : 2

 

먼저 8행의 z = x++;의 결과에서 ++연산자보다 = 연산자가 먼저 실행된 것을 알 수 있습니다.

즉 다음과 같이 x 값을 z에 대입한 후 x의 값이 하나 증가하는 순서로 연산이 실행됩니다.

z = x;

z = x + 1;

 

그런데 11행의 z = ++y의 결과를 살펴보면 = 연산자보다 ++연산자가 먼저 실행된 것을 알 수 있습니다.

즉 다음과 같이 y의 값을 하나 증가시킨 후 증가한 y값을 z에 대입하는 순서로 연산이 실행됩니다.

y = y + 1;

z = y;

 

++xx++의 차이는 완전히 다른 결과를 가져옵니다.

따라서 연산자의 위치와 정확한 사용 방법을 이해하는 것은 프로그래밍에서 아주 중요합니다.

 

[ 029 ] - 연산자가 복잡해지면 괄호를 사용하자.

주변에 영어를 잘하는 사람을 보면 우리가 중학교 때 배운 문장이나 단어만으로도 외국인과 어려운 없이 대화하는 것을

볼 수 있습니다. 하지만 어려울 것 없는 단어들을 조합해서 문장을 만들고 이 문장의 형태로 말하거나 듣는 것은

쉽지 않습니다. 프로그래밍도 영어를 구사하는 것과 비슷합니다. 잘 사용하지도 않는 연산자나 복잡한 알고리즘을

모두 외운다고 해서 프로그래밍의 고수가 되는 것이 아닙니다.

오히려 고수들의 프로그램은 의외로 단순하고 간단 명료한 경우가 대부분인데,

하나의 특징은 고수 프로그래머의 코드에는 다른 사람이 봤을 때 이해하기 어렵거나 모호하게 기능을 구현한 코드가

없다는 것입니다. 이와 같이 고수 프로그래머들이 구현한 프로그램에서 자주 볼 수 있는 것이 초보 프로그래머가

복잡하고 길게 나열해서 구현하는 기능을 간결하게 바꾸고 깔끔하게 정리해서 구현한다는 것입니다.

이와 같이 복잡하고 이해하기 힘든 코드를 간결하고 보기 쉽고 간단하게 정리하는

노하우 가운데 하나가 연산자가 복잡해지면 괄호로 묶어서 우선순위를 명확하게 구분하는 습관을 갖는 것입니다.

 

[ 030 ] - 새로운 자료형을 선언할 때는 typedef를 사용하자.

typedef를 사용하면 새로운 연산자를 만들어 사용할 수 있습니다.

typedef는 구조체형을 선언할 때 가장 많이 사용합니다.

typedef struct _Node {

        char *data;

        struct _Node *Next;

} NODE;

 

typedef는 구조체형을 선언하는 것 이외에 복잡한 부분을 한눈에 알 수 있도록 사용하는 경우도 있습니다.

예를 들면 unsigned char A;라고 하면 A의 자료형이 unsigned char형이지만 실제 어떤 목적으로 사용되는

변수인지 알기 어렵기 때문에, 이 때 typedef를 이용해서 unsigned char를 SENSOR로 표현해 두면

변수 A가 센서의 역할을 한다는 것을 쉽게 알 수 있습니다.

typedef unsigned char SENSOR;

SENSOR A;

 

정수형 데이터를 갖는 학점을 사용하는 경우라면 다음과 같이 typedef를 사용할 수 있습니다.

typedef unsigned int GRADE;

 

GRADE Korean;

GRADE English;

GRADE Math;

 

GRADE로 선언된 Korean, English, Math라는 변수만 보고도

이 변수들의 사용 목적이 학점을 표시하기 위한 것임을 쉽게 알 수 있습니다.

Posted by devanix