#visualstudio - _noop 키워드
NOOP
혹은 NOP
로 사용하는데, NO OPerator의 줄임말이다. 말 그대로 아무런 연산을 하지 않는 명령어를 뜻한다. 표준이 아니라 VC++ 키워드라는 게 걸리는데, 다른 컴파일러에서 동작하도록 쉽게 수정할 수 있으니 포팅 걱정은 안 하고 VC++에서 편하게 써도 된다. VC++ 이외의 컴파일러에서는 (void(0))
를 사용하면 된다.
#include <stdio.h>
#if DEBUG
# define PRINT printf_s
#else
# define PRINT __noop
#endif
int main()
{
PRINT("\nhello\n");
return 0;
}
_noop – MSDN에서 예제를 가져왔다. 에이 이걸로 끝? #define PRINT __noop
와 #define PRINT
둘 사이에 다른 게 없다고 생각할지 모르는데, 다르다. 다음 예제를 보자.
#include <stdio.h>
#if DEBUG
# define PRINT printf_s
#else
# define PRINT
#endif
const char* GetOutputString()
{
printf_s("DEBUG가 0일때 호출되나?\n");
return "hello";
}
int main()
{
PRINT("%s\n", GetOutputString());
return 0;
}
_noop 키워드를 사용하지 않고 비워두었다. GetOutputString()은 호출될까? pre-processor에 의해 PRINT(“%s\n”, GetOutputString());
은 (“%s\n”, GetOutputString());
으로 변경되고 아무런 동작을 하지 않지만 GetOutputString() 함수를 호출한다. 그래서 위의 소스 코드를 release 빌드해서 실행해 보면 “DEBUG가 0일 때 호출되나?” 문장이 출력된다.
_noop 키워드를 쓰면 __noop(“%s\n”, GetOutputString());
으로 변경되고 이 문 자체가 실행되지 않고 싹 무시된다.
#include <stdio.h>
#if DEBUG
# define PRINT(...) printf_s(__VA_ARGS__)
#else
# define PRINT(...)
#endif
const char* GetOutputString()
{
printf_s("DEBUG가 0일때 호출되나?\n");
return "hello";
}
int main()
{
PRINT("%s\n", GetOutputString());
return 0;
}
사실 프로그래머 대부분은 이렇게 인자(argument)까지 define 하는 걸 선호하고 사용한다. 이렇게 작성하면 위와 같은 문제도 없어진다. C99를 지원하지 않아서 Variadic Macros를 사용할 수 없는 컴파일러라면 위와 같이 이름만 define 할지도 모르겠다.
그리고 한 가지 이점이 더 있는데, 비워두지 않고 __noop
키워드를 쓰면 어떤 매크로가 무시되는지 검색하기가 편리하다.
포스팅하는데 발단이 된 게시물 : 자신이 만든 디버그 메시지출력 조절 - GPGstudy