[Software c언어] 매크로 #define 활용

매크로 #define활용”Software”

c언어에서 지원하는 특별한 기능인 매크로(#define)에 대해 알아보고 활용해 보자.#define 사용법

우선 #define(매크로)은 다음과 같이 선언한다.

NAME은 내가 사용하고 싶은 이름이고 오른쪽에는 그 이름으로 사용하고 싶은 어떤 “값”을 넣는다.이 「값」에는 통상 정수가 들어가지만, 때로는 (상당히 많은 경우) 함수가 들어가기도 한다.

그럼 실제로 어떻게 사용하는지 코드로 살펴보자.

#define이 어떻게 사용되는지 쉽게 보여주기 위해 만든 간단한 코드다.상기는 1, 0, -1을 각각 TRUE, FALSE, ERROR로 대체하여 쓴 것이다.

#define을 왜 사용하는지

만약 #define(매크로)을 처음 공부한다면 이런 생각이 들 것이다.(나도 그랬다)

” 이걸 왜 쓰지? “

” 앞 코드에서 그냥 1,0,-1로 써도 결과는 똑같은데 왜 이렇게 바꿔서 쓰는 거야?

” 굳이 메모리를 더 쓰면서까지 왜 바꿔서 쓰는걸까?? “

” 그냥 변수 쓰는 거랑 뭐가 달라? “

위와 같은 생각에 대한 나의 대답은 다음과 같다.

가독성이 높아지다.

코드를 짠 사람은 1, 0, – 1이 무엇을 의미하는지, 무엇을 의도하고 썼는지에 대해 알고 있지만, 다른 사람이 코드를 봤을 때는 그 숫자나 함수가 무엇을 의미하는지 파악하기 어렵다(더욱이 시간이 지나면 코드를 짠 본인도 잊어버리는 경우도 많다)가 위와 같이 1->TRUE, 0->FALSE처럼 매핑(Mapping)시키면 코드가 읽기 쉬워진다.

코드 수정이 쉬워진다.

어떤 배열을 선언한다고 해보자.c언어에서는 malloc()이나 calloc()와 같이 동적 할당을 해주는 함수를 사용하지 않으면 배열의 [ ] 안에 변수를 넣어 선언하는 것은 불가능하다.이는 만약 개발자가 동적 할당을 할 의도가 없는 경우에는 어떠한 정수로 배열의 크기를 결정해야 한다는 것인데, 그렇다면 다음과 같이 배열을 선언해야 한다.

한 프로그램이 위 배열을 함수 10곳에서 사용한다고 가정하자.예를 들어, 상기 배열의 모든 요소를 출력하는 함수는 다음과 같은 코드가 필요하다.

그런데 만약 위 코드에서 배열의 크기를 다음과 같이 수정한다고 해보자.

이래서는 매우 성가신 문제가 발생한다.이 배열을 사용할 10개의 함수를 찾아 수정해야 한다.만약 프로그램이 코드 길이가 매우 긴 프로그램이라면 이러한 수정이 필요할 때마다 매우 번거로워지고 빼서 수정하지 못할 경우 버그가 발생할 수 있다.

그렇다면 이번에는 #define(매크로)을 이용해 배열을 선언해 보자.

10 x 10의 크기를 갖는 배열을 다음과 같이 매크로를 이용하여 선언할 수 있을 것이다.그리고 상기 배열이 사용되는 함수도 다음 매크로를 이용하여 정의되어 있다고 하자.

이번에는 위와 같은 코드에서 전술한 바와 같이 SIZE를 10=>5로 수정해야 하는 상황이 발생했다고 해보자.그렇다면 개발자는 오직 다음 코드 한 줄만 수정하면 된다.

이처럼 매크로를 자주 이용하면 코드 수정이 매우 간단해지는 장점이 있다.

메모리를 빼지 않는다.

변수는 기본 선언되면 해당 데이터 유형에 맞는 메모리 크기가 할당된다.ex) char : 1byte, int : 4byte etc… 그러나 #define(매크로)을 이용하여 정의된 상수 및 함수는 메모리가 할당되지 않는다.어떻게 이런 마법이 가능하냐면 매크로는 동작원리가 치환이라는 점이다.매크로는 개발자가 지정한 값을 저장하고 있는 것이 아니라 개발자가 선언해 놓은 매크로가 존재한다는 것만 컴퓨터가 알고 있는 채 코드를 쭉 읽어나가다가 선언된 매크로가 나오면 해당 값으로 대체한다.(전처리기 작업 중에 일어나는 일)

빠르다.

상기에서 설명한 바와 같이 매크로 함수는 전처리기 작업이지 함수 호출을 통한 동작이 아니기 때문에 일반 함수보다 실행 속도가 빠르다는 장점이 있다.매크로 함수

위에서 매크로를 설명하기 위한 예로서 정수를 이용해 설명했다.그러나 매크로를 이용해 함수도 정의할 수 있다.예를 들어 어떤 문자열을 컴퓨터 화면으로 출력하려면 다음과 같은 코드가 필요하다.

그러나 개인의 편의를 위하여 혹은 가독성을 높이기 위하여 상기 코드를 다음과 같이 바꾸어 사용할 수도 있다.

매크로의 암묵적인 규칙

프로그래밍을 하다 보면 꼭 지켜야 하는 것은 아니지만 개발자들 사이에서 암묵적으로 대다수 사람들이 따르는 규칙 같은 것이 존재한다.

예를 들어 자바에서 클래스는 대문자로 시작한다든가, c언어에서는 변수나 함수의 이름을 붙일 때 단어와 단어 사이를 _로 연결한다든가 개발자 사이에 ‘룰’이 있다.

이는 거시적으로도 존재한다.

#define(매크로)로 정의하는 정수 혹은 함수는 모두 대문자로 만든다는 것이다.내가 봐왔던 결과로는 함수 같은 경우는 이 규칙을 따르는 경우도 있고 따르지 않는 경우도 많이 봤는데.적어도 정수에 한해서는 프로그래밍 초보자가 아닌 이상 모두 대문자로 명명했다.

그리고 매크로의 경우는 보통 #include 바로 밑에 모아서 정의를 해두는 경우가 많다.아래는 내가 짠 코드에서 정의한 매크로이다. (예를 들어보기 위해 가져온다)

※ 매크로 사용 시 주의사항 ※

내가 위에 매크로에 대한 장점을 계속 적어놨어.그러나 항상 무엇이든 단점 혹은 주의해야 할 점이 있다.

매크로에서 정수를 정의하고 사용하는 경우는 거의 문제가 없지만 함수를 정의하는 경우는 문제가 발생할 수 있다.

상기와 같은 함수를 정의했다고 해보자.상기 함수는 통상적인 경우에는 값을 정확하게 인쇄할 것이다.예를 들어, SQUARE(10) 혹은 SQUARE(5)를 호출하면 100, 25를 잘 인쇄할 것이다.

그런데 만약, SQUARE(2+5)를 호출했다고 해 보자.보통 함수라면 정확히 49를 인쇄할 것이다.

그러나 위의 매크로 함수는 17을 인쇄한다!!

왜 이런 결과를 내는지 생각해 보자.

마크로는 문자열을 바꾸겠다고 말했다.이러한 개념을 바탕으로 생각해 보면 위의 결과는 당연하다.SQUARE(2+5)는 7*7이 아니라 (2+5*2+5)라는 연산을 수행하기 때문이다.

나도 위 내용을 모르는 상태에서 프로그램을 짜다가 디버깅을 하다가 밤을 새웠던 기억이 있다.매크로 함수는 이러한 위험이 있으므로 매크로 함수를 정의할 경우 위와 같은 상황이 발생할 수 있는지 판별하여 사용해야 한다.

  • 피드백은 항상 환영합니다.

error: Content is protected !!