IT이야기

(void) 0이 C와 C++에서 작동하지 않는 이유는?

cyworld 2022. 5. 21. 08:55
반응형

(void) 0이 C와 C++에서 작동하지 않는 이유는?

내부적으로 다음과 같이 정의된 glibc에서 디버그 인쇄fs를 본 적이 있다.(void) 0, NDEBUG가 정의된 경우.마찬가지로 비주얼 C++ 컴파일러도 거기에 있다.전자는 GCC와 VC++ 컴파일러 모두에서 작동하며, 후자는 VC++에서만 작동한다.이제 우리 모두는 위의 두 진술이 모두 아무런 조작도 없고 각각의 코드가 생성되지 않을 것이라는 것을 알고 있다. 하지만 여기서 나는 의심이 간다.

의 경우__noopMSDN은 그것이 컴파일러에 의해 제공되는 본질적인 함수라고 말한다.로 오는 중(void) 0왜 컴파일러에 의해 수술을 하지 않는 것으로 해석되는가?C언어를 까다롭게 사용하는 것인가, 아니면 표준이 그것을 탐구적으로 말하는 것인가?아니면 그것조차 컴파일러 구현과 관련이 있는가?

(void)0(+; '도 하지 않는'은 타당하지만 '아무것도 안하는' C++ 표현, 그것이 전부다.로 번역되지 않는다.no-op대상 아키텍처의 지시, 언어가 완전한 문(예: 점프 라벨의 표적 또는 본문)을 기대할 때마다 자리 표시자로 빈 문일 뿐이다.if절이다.

편집: (Chris Lutz의 코멘트를 기반으로 업데이트됨)

매크로로 사용할 때는 다음과 같이 해야 한다.

#define noop ((void)0)

(void)그것이 우연히 다음과 같은 가치로 사용되는 것을 방지하다.

int x = noop;

위의 식에 대해 컴파일러는 이를 잘못된 작업으로 올바르게 플래그 지정한다.는 GCC를 .error: void value not ignored as it ought to be및 VC++ 나무껍질'void' illegal with all types.

내 생각에 당신은 glib가 아닌 glibc를 말하는 것 같은데 문제의 매크로가 바로 the macro이다.assert매크로:

glibc's eathero.<assert.h>와 함께NDEBUG (문서 없음),assert다음과 같이 정의된다.

#ifdef NDEBUG
#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif
# define assert(expr)           (__ASSERT_VOID_CAST (0))
#else
/* more code */
#endif

그 말은 기본적으로assert(whatever);((void)(0));그리고 아무것도 하지 않는다.

C89 표준(섹션 4.2):

머리글<assert.h>을 규정하다assert매크로(macro)와 다른 매크로(macro)를 가리킨다.

NDEBUG

은 의의 않에 .<assert.h>. 만약NDEBUG소스 파일의 지점에서 매크로 이름으로 정의되며,<assert.h>되어 있다.assert매크로는 단순히 로 정의된다.

#define assert(ignore) ((void)0)

디버그 인쇄 매크로를 정의하는 것이(void)0일리가 있다. 수 있니어디서 하는지 보여줄 수 있어?

부작용이 없는 표현은 컴파일러에 의해 거부반응으로 처리될 수 있는데, 컴파일러는 그것에 대해 어떤 코드도 생성하지 않아도 된다.우연히 캐스팅을 한 다음 캐스팅 결과를 사용하지 않는 것은 컴파일러(및 인간)가 부작용을 갖지 않는 것으로 보기 쉽다.

그렇다고 해도, 왜 활자가 그것을 무효로 만들었을까?또한 #define dbgprintf (void) 0의 경우 dbgprintf("Hello World!")와 같이 불릴 때 -> (void) 0("Hello World!"); - 무슨 뜻인가?– 레전드2k

매크로가 코드를 다른 것으로 대체하므로 #defined dbgprint(x를 수락하는 dbgprint)를 다음과 같이 정의하십시오.

무효(0)

그러면 X를 교체할 때 다시 쓸 수 없으므로 dbgprintf("Hellowworld")는 (void) 0("Hello world")로 변환되지 않고 (void) 0으로 변환된다. - 매크로 이름 dbgprint는 (void) 0으로 대체될 뿐만 아니라 전체 통화 dbgprintf("...")

Windows에서 Main.cpp:

#include <iostream>
#define TRACE ((void)0)
int main() {
  TRACE("joke");
  std::cout << "ok" << std::endl;
  return 0;
}

그런 다음 Main.i 출력으로 Release version exe 파일을 빌드한다.Main.i 파일에서 TRACE 매크로는 다음과 같이 대체되었다.((void)0)("joke"), 그리고 비주얼 스튜디오는 다음과 같이 경고한다:"경고 C4353: 비표준 확장 사용: 함수 표현으로 상수 0.대신 '_noop' 함수의 고유 함수를 사용하십시오."exe 파일을 실행하고 콘솔에서 "확인" 문자를 인쇄하십시오.그래서 나는 모든 것이 명확하다고 생각한다: 매크로 TRACE[#define TRACE ((void)0)]의 정의는 c++ 구문에 따라 불법이지만, 비주얼 스튜디오의 c+++ 컴파일러는 컴파일러 확장자로서 이러한 행위를 지원한다.결론은 [#Define TRACE ((void)0)]는 불법 c++ 문장이며, 기껏해야 이것을 사용하지 마십시오.그러나 [#TRACE(x) ((void)0)]은 법적 진술이다.그게 다야.

참조URL: https://stackoverflow.com/questions/2198950/why-is-void-0-a-no-operation-in-c-and-c

반응형