C/C++에서 #define 전처리기 정의를 이용해 매크로 함수를 만든 것을 종종 볼 수 있다.


#define abs(a)   (((a) > 0) ? (a) : (-a))   // 절대값 계산

#define max(a,b)   (((a) > (b)) ? (a) : (b))  // a, b 중 큰 값을 찾는다.

#define min(a,b)    (((a) < (b)) ? (a) : (b)) // a, b 중 작은 값을 찾는다.

#define i2m(i) ((i)*25.4)   // 인치 단위로 변환

#define m2i(m)  ((m)/25.4)  // 밀리미터 단위로 변환


보통 위와 같은 형태로.


그런데, 최근에 암호화 알고리즘 관련해 C로 된 소스 코드를 구해서 C#으로 컨버전을 하다 아무리 해도, 컨버전은 확실히 잘 됐는데, 이상하게도 결과가 맞지 않는 것이 있어 좀 들여다 봤더니...


정말 이상했다.


아래와 같은 매크로 함수가 예상과 다르게 동작하는 것이 아닌가?

아래 예제에서 a와 b의 결과는 어떻게 될까?


#define Func1(A, B) { \

A += B; \

A ^= B; B ^= A; \

}


int main()

{

DWORD a, b;

a = 15;

b = 20;

Func1(a, b);

printf("a: %d, b: %d\n", a, b);

return 0;

}


상식적으로 판단하기엔, DWORD는 unsigned long이므로 값 형식이다. 따라서 함수 호출 시 포인터로 넘겨주지 않았으므로 함수 호출 결과는 원래 DWORD 값에 영향을 미칠 수 없어야 한다.


그런데, 결과를 찍어보면

a: 55, b: 35


이렇게 바뀐 값으로 찍힌다.


아니, 이게 무슨??????


이렇게 생각하면 곤란하다. 나도 저렇게 생각했었다. 털썩;;;


조금만 더 생각해보면,

당연하게도, #define으로 정의된 매크로 함수는 함수가 아니라, 치환될 내용일 뿐이다.


즉, 위 예제를 실제로 실행될 때는 Func1(A, B); 부분이 #define으로 정의된 매크로 함수 내용으로 대체되는 것이다.


int main()

{

DWORD a, b;

a = 15;

b = 20;

{  a += b; a ^= b; b ^= a; }

printf("a: %d, b: %d\n", a, b);

return 0;

}


이렇게.


그러니까 값이 바뀌는 것이 당연.


매크로 함수가 함수처럼 생겼다고 함수로 오해하면 절~~대 안되겠다. 헐.






Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]