문제

나는 조금 썼다. , 그리고 그것이 무엇을 하고 있는지에 대한 일반적인 아이디어를 얻을 만큼 충분히 잘 읽을 수 있지만 매크로를 만날 때마다 그것은 나를 완전히 당황하게 했습니다.결국 매크로가 무엇인지 기억하고 읽으면서 머리 속으로 대체해야 합니다.제가 만난 직관적이고 이해하기 쉬운 것들은 늘 작은 미니 함수 같았는데, 왜 단순한 함수가 아닌지 늘 궁금했습니다.

전처리기에서 디버그 또는 크로스 플랫폼 빌드를 위해 다양한 빌드 유형을 정의해야 하는 필요성을 이해할 수 있지만 임의 대체를 정의하는 기능은 이미 어려운 언어를 이해하기 더욱 어렵게 만드는 데에만 유용한 것 같습니다.

이렇게 복잡한 전처리기가 도입된 이유는 무엇입니까? ?그리고 #debug 스타일의 조건부 컴파일이 아닌 다른 목적으로 여전히 사용되는 것처럼 보이는 이유를 이해할 수 있는 사용 예가 있는 사람이 있습니까?

편집하다:

여러 답변을 읽어도 여전히 이해가 되지 않습니다.가장 일반적인 대답은 인라인 코드입니다.inline 키워드가 이를 수행하지 않으면 이를 수행하지 말아야 할 타당한 이유가 있거나 구현을 수정해야 합니다."이 코드를 실제로 인라인"(인라인이 사용되기 전에 작성된 코드는 제외)을 의미하는 완전히 다른 메커니즘이 필요한 이유를 이해하지 못합니다.또한 "함수에 넣기에는 너무 어리석은 경우"라는 아이디어를 이해하지 못합니다.확실히 입력을 받아 출력을 생성하는 코드 조각은 함수에 넣는 것이 가장 좋습니다.글쓰기의 미세한 최적화에 익숙하지 않기 때문에 이해하지 못할 수도 있다고 생각합니다. , 그러나 전처리기는 몇 가지 간단한 문제에 대한 복잡한 솔루션처럼 느껴집니다.

도움이 되었습니까?

해결책

나는 매크로가 무엇인지 기억하고 내가 읽을 때 내 머리에 그것을 대체해야한다.

그것은 매크로의 이름을 잘 반영하지 않는 것 같습니다. 나는 당신이 전처리 서를 에뮬레이션 할 필요가 없다고 가정합니다. log_function_entry() 매크로.

내가 직관적이고 이해하기 쉬운 사람들은 항상 작은 미니 기능과 같았으므로 왜 그들이 왜 단지 기능을했는지 궁금했습니다.

일반적으로 일반 매개 변수에서 작동 할 필요가 없다면 이루어져야합니다.

#define max(a,b) ((a)<(b)?(b):(a))

An과 모든 유형에서 작동합니다 < 운영자.

더 많은 기능을 통해 Macros를 사용하면 소스 파일의 기호를 사용하여 작업을 수행 할 수 있습니다. 즉, 새 변수 이름을 만들거나 매크로가 켜진 소스 파일 및 줄 번호를 참조 할 수 있습니다.

C99에서 Macros는 Printf와 같은 Variadic 함수를 호출 할 수 있습니다.

#define log_message(guard,format,...) \
   if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);

log_message( foo == 7, "x %d", x)

형식은 printf와 같이 작동합니다. 가드가 참이면 메시지를 인쇄 한 파일 및 줄 번호와 함께 메시지를 출력합니다. 함수 호출이라면 파일과 줄을 알지 못하고 vaprintf 조금 더 많은 일이 될 것입니다.

다른 팁

이 발췌문은 몇 가지 방법을 비교 하여이 문제에 대한 내 견해를 거의 요약합니다. C 매크로가 사용되며이를 구현하는 방법 D.

DigitalMars.com에서 복사했습니다

다시 C 발명되었고, 컴파일러 기술은 원시적이었습니다. 텍스트 매크로 사전 처리기를 프론트 엔드에 설치하는 것은 많은 강력한 기능을 추가 할 수있는 간단하고 쉬운 방법이었습니다. 프로그램의 규모와 복잡성이 증가함에 따라 이러한 기능에는 많은 고유 한 문제가 있습니다. D 전처리자가 없습니다. 하지만 D 동일한 문제를 해결하기위한보다 확장 가능한 수단을 제공합니다.

매크로

전처리 매크로는 강력한 기능과 유연성을 추가합니다 C. 그러나 그들은 단점이 있습니다.

  • 매크로는 범위의 개념이 없습니다. 정의 지점에서 소스의 끝까지 유효합니다. 그들은 .h 파일, 중첩 코드 등을 가로 질러 Swath를 자릅니다. #include'수만 개의 매크로 정의 라인에서 부주의 한 거시적 확장을 피하는 것이 문제가됩니다.
  • 매크로는 디버거에게 알려지지 않았습니다. 상징적 인 데이터로 프로그램을 디버깅하려고 시도하는 것은 매크로 자체가 아니라 거시적 확장에 대해 아는 디버거로 인해 손상됩니다.
  • 매크로는 초기 거시적 변화가 임의로 토큰을 다시 실행할 수 있으므로 소스 코드를 토큰 화하는 것이 불가능합니다.
  • 매크로의 순전히 텍스트 기반은 임의적이고 일관되지 않은 사용으로 이어져 매크로 오류를 사용하여 코드를 만듭니다. (일부를 해결하려는 시도는 템플릿으로 도입되었습니다. C++.)
  • 매크로는 여전히 헤더 파일 주변의 "랩퍼"와 같은 언어 표현 기능의 결함을 보완하는 데 사용됩니다.

다음은 매크로에 대한 일반적인 용도의 열거와 d의 해당 기능입니다.

  1. 문자 그대로 상수 정의 :

    • 그만큼 C 사전 처리기 방법

      #define VALUE 5
      
    • 그만큼 D 방법

      const int VALUE = 5;
      
  2. 값 또는 플래그 목록 작성 :

    • 그만큼 C 사전 처리기 방법

      int flags:
      #define FLAG_X  0x1
      #define FLAG_Y  0x2
      #define FLAG_Z  0x4
      ...
      flags |= FLAG_X;
      
    • 그만큼 D 방법

      enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 };
      FLAGS flags;
      ...
      flags |= FLAGS.X;
      
  3. 기능 호출 규칙 설정 :

    • 그만큼 C 사전 처리기 방법

      #ifndef _CRTAPI1
      #define _CRTAPI1 __cdecl
      #endif
      #ifndef _CRTAPI2
      #define _CRTAPI2 __cdecl
      #endif
      
      int _CRTAPI2 func();
      
    • 그만큼 D 방법

      컨벤션을 블록으로 지정할 수 있으므로 모든 기능에 대해 변경할 필요가 없습니다.

      extern (Windows)
      {
          int onefunc();
          int anotherfunc();
      }
      
  4. 간단한 일반 프로그래밍 :

    • 그만큼 C 사전 처리기 방법

      텍스트 대체를 기반으로 사용할 기능 선택 :

      #ifdef UNICODE
      int getValueW(wchar_t *p);
      #define getValue getValueW
      #else
      int getValueA(char *p);
      #define getValue getValueA
      #endif
      
    • 그만큼 D 방법

      D 다른 기호의 별칭 인 기호의 선언을 활성화합니다.

      version (UNICODE)
      {
          int getValueW(wchar[] p);
          alias getValueW getValue;
      }
      else
      {
          int getValueA(char[] p);
          alias getValueA getValue;
      }
      

더 많은 예가 있습니다 DigitalMars 웹 사이트.

그들은 C 위에있는 프로그래밍 언어 (더 간단한 언어)이므로 컴파일 시간에 Metaprogramming을 수행하는 데 유용합니다 ... 즉, C 코드를 적은 줄과 시간으로 생성하는 매크로 코드를 작성할 수 있습니다. C에서 직접 쓰기

또한 "다형성"또는 "과부하"인 "표현과 같은"기능을 작성하는 데 매우 유용합니다. 예 : 최대 매크로는 다음과 같이 정의됩니다.

#define max(a,b) ((a)>(b)?(a):(b))

모든 숫자 유형에 유용합니다. 그리고 C에서는 다음을 쓸 수 없었습니다.

int max(int a, int b) {return a>b?a:b;}
float max(float a, float b) {return a>b?a:b;}
double max(double a, double b) {return a>b?a:b;}
...

원한다고해도 기능을 과부하시킬 수 없기 때문입니다.

그리고 조건부 컴파일 및 파일은 말할 것도없이 (매크로 언어의 일부이기도합니다) ...

매크로를 사용하면 편집 시간 동안 누군가가 프로그램 동작을 수정할 수 있습니다. 이걸 고려하세요:

  • C 상수는 개발 시간에 프로그램 동작을 수정할 수 있습니다
  • C 변수는 실행 시간에 프로그램 동작을 수정할 수 있습니다
  • C 매크로는 컴파일 시간에 프로그램 동작을 수정할 수 있습니다

컴파일 시간은 미사용 코드가 바이너리로 들어가지 않으며 빌드 프로세스가 거시적 사전 처리기와 통합되는 한 값을 수정할 수 있음을 의미합니다. 예 : ARCH = ARM MAKE (CC -Darch = ARM으로 매크로 정의를 전달합니다)

간단한 예 : (glibc limits.h에서 가장 큰 값을 정의)

#if __WORDSIZE == 64
#define LONG_MAX 9223372036854775807L
#else
#define LONG_MAX 2147483647L
#endif

32 또는 64 비트를 컴파일하는 경우 컴파일 시간에 (#Define __wordsize를 사용) 확인합니다. Multilib 도구 체인을 사용하면 매개 변수 -m32 및 -m64를 사용하면 비트 크기를 자동으로 변경할 수 있습니다.

(POSIX 버전 요청)

#define _POSIX_C_SOURCE 200809L

컴파일 시간 동안 요청. POSIX 2008 지원. 표준 라이브러리는 많은 (양립 할 수없는) 표준을 지원할 수 있지만이 정의를 통해 올바른 기능 프로토 타입 (예 : getline (), gets () 등을 제공합니다. 라이브러리가 표준을 지원하지 않으면 예를 들어 실행 중에 충돌하는 대신 컴파일 시간 동안 #ERROR를 제공 할 수 있습니다.

(하드 코드 경로)

#ifndef LIBRARY_PATH
#define LIBRARY_PATH "/usr/lib"
#endif

컴파일 시간 동안 하드 코드 디렉토리를 정의합니다. 예를 들어 -dlibrary_path =/home/user/lib로 변경할 수 있습니다. 그것이 const char *라면, 편집 중에 어떻게 구성 하시겠습니까?

(pthread.h, 컴파일 시간에 복잡한 정의)

# define PTHREAD_MUTEX_INITIALIZER \
  { { 0, 0, 0, 0, 0, 0, { 0, 0 } } }

그렇지 않으면 단순화되지 않은 큰 텍스트가 (항상 컴파일 시간에) 선언 될 수 있습니다. 함수 또는 상수 (컴파일 시간에) 로이 작업을 수행 할 수 없습니다.

실제로 복잡한 것을 피하고 코딩 스타일이 좋지 않은 것을 제안하지 않기 위해 다른 양립 할 수없는 운영 체제에서 컴파일하는 코드의 예를 제시하지 않습니다. 크로스 빌드 시스템을 사용하십시오. 그러나 전처리 기준은 결근으로 인해 컴파일을 깨지 않고 빌드 시스템의 도움없이이를 허용하는 것이 분명해야합니다.

마지막으로, 프로세서 속도와 메모리가 제한되고 시스템이 매우 이질적인 내장 시스템에서 조건부 편집의 중요성에 대해 생각해보십시오.

이제 물어 보면 모든 매크로 상수 정의 및 기능 호출을 적절한 정의로 대체 할 수 있습니까? 대답은 그렇습니다. 그러나 편집 중에 프로그램 행동을 변경 해야하는 것은 단순히 사라지지 않습니다. 전처리 기는 여전히 필요합니다.

매크로(및 전처리기)는 C 초기부터 나왔다는 점을 기억하세요.이는 인라인 '함수'를 수행하는 유일한 방법이었으며(물론 inline은 매우 최근의 키워드이기 때문에) 여전히 무언가를 인라인하도록 강제하는 유일한 방법입니다.

또한 매크로는 컴파일 타임에 파일과 줄을 문자열 상수에 삽입하는 것과 같은 트릭을 수행할 수 있는 유일한 방법입니다.

요즘에는 매크로가 유일한 방법이었던 많은 작업이 새로운 메커니즘을 통해 더 잘 처리됩니다.그러나 그들은 때때로 여전히 자신의 자리를 가지고 있습니다.

효율성 및 조건부 편집을위한 인라인 외에도 매크로는 저수준 C 코드의 추상화 수준을 높이는 데 사용될 수 있습니다. C는 실제로 메모리 및 리소스 관리에 대한 핵심적인 세부 사항과 데이터의 정확한 레이아웃에서 당신을 격리시키지 않으며 대규모 시스템 관리를위한 매우 제한된 형태의 정보 숨기기 및 기타 메커니즘을 지원합니다. 매크로를 사용하면 더 이상 C 언어의 기본 구성 만 사용하는 것으로 제한되지 않습니다. 여전히 C는 명목상 C!

사전 처리기 매크로는 실제로 a 튜링-완성 컴파일 시간에 실행 된 언어. 이것의 인상적인 (그리고 약간 무서운) 예 중 하나는 C ++ 측면에 있습니다. 사전 처리기를 부스트하십시오 도서관을 사용합니다 C99/C ++ 98 사전 처리기는 (상대적으로) 안전한 프로그래밍 구조를 구축하여 C ++에 관계없이 기본 선언 및 입력 코드로 확장됩니다.

실제로, 더 안전한 언어로 높은 수준의 구조물을 사용할 위도가 없을 때 전 처리기 프로그래밍을 최후의 수단으로 추천합니다. 그러나 때로는 등이 벽에 대고 족제비가 닫히면 무엇을 할 수 있는지 아는 것이 좋습니다.

에서 컴퓨터의 어리석음:

나는 UNIX용 프리웨어 게임 프로그램에서 발췌한 다음 코드를 보았습니다.

/*
* 비트 값.
*/
#BIT_0 정의 1
#BIT_1 정의 2
#BIT_2 정의 4
#BIT_3 정의 8
#BIT_4 정의 16
#BIT_5 정의 32
#BIT_6 정의 64
#BIT_7 정의 128
#BIT_8 정의 256
#define BIT_9 512
#BIT_10 1024 정의
#BIT_11 2048 정의
#define BIT_12 4096
#define BIT_13 8192
#BIT_14 16384 정의
#BIT_15 32768 정의
#BIT_16 65536 정의
#define BIT_17 131072
#BIT_18 262144 정의
#BIT_19 524288 정의
#BIT_20 1048576 정의
#define BIT_21 2097152
#define BIT_22 4194304
#BIT_23 8388608 정의
#BIT_24 정의 16777216
#BIT_25 33554432 정의
#BIT_26 67108864 정의
#BIT_27 정의 134217728
#BIT_28 268435456 정의
#BIT_29 536870912 정의
#BIT_30 1073741824 정의
#BIT_31 2147483648 정의

이를 달성하는 훨씬 쉬운 방법은 다음과 같습니다.

#define BIT_0 0x00000001
#BIT_1 0x00000002 정의
#BIT_2 0x00000004 정의
#BIT_3 0x00000008 정의
#BIT_4 0x00000010 정의
...
#define BIT_28 0x10000000
#define BIT_29 0x20000000
#define BIT_30 0x40000000
#define BIT_31 0x80000000

더 쉬운 방법은 컴파일러가 계산을 수행하도록 하는 것입니다.

#BIT_0 정의 (1)
#define BIT_1 (1 << 1)
#define BIT_2 (1 << 2)
#define BIT_3 (1 << 3)
#define BIT_4 (1 << 4)
...
#define BIT_28 (1 << 28)
#define BIT_29 (1 << 29)
#define BIT_30 (1 << 30)
#define BIT_31 (1 << 31)

그런데 왜 32개의 상수를 정의하는 데 어려움을 겪을까요?C 언어에도 매개변수화된 매크로가 있습니다.정말로 필요한 것은 다음과 같습니다.

#define BIT(x) (1 << (x))

어쨌든 원래 코드를 작성한 사람이 계산기를 사용했는지 아니면 그냥 종이에 다 계산했는지 궁금합니다.

이는 매크로를 사용할 수 있는 한 가지 방법일 뿐입니다.

매크로가 실제로 빛나는 경우 중 하나는 코드 생성을 할 때입니다.

나는 자신의 방법이있는 플러그인 시스템을 사용하여 매개 변수를 플러그인으로 전달하는 (사용자 정의 맵과 같은 구조를 사용)를 사용하는 오래된 C ++ 시스템에서 작업했습니다. 일부 간단한 매크로는이 퀴크를 다루는 데 사용되었으며 너무 많은 문제없이 플러그인의 정상적인 매개 변수와 함께 실제 C ++ 클래스와 기능을 사용할 수있었습니다. 매크로에 의해 생성되는 모든 접착제 코드.

이미 말한 내용에 추가하겠습니다.

매크로는 텍스트 대체에 대해 작동하기 때문에 함수를 사용하여 수행할 수 없는 매우 유용한 작업을 수행할 수 있습니다.

매크로가 정말 유용할 수 있는 몇 가지 경우는 다음과 같습니다.

/* Get the number of elements in array 'A'. */
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))

매우 유명하고 자주 사용되는 매크로입니다.예를 들어 배열을 반복해야 할 때 매우 편리합니다.

int main(void)
{
    int a[] = {1, 2, 3, 4, 5};
    int i;
    for (i = 0; i < ARRAY_LENGTH(a); ++i) {
        printf("a[%d] = %d\n", i, a[i]);
    }
    return 0;
}

여기서는 다른 프로그래머가 5개의 요소를 더 추가하더라도 문제가 되지 않습니다. a 선언에서.그만큼 for-루프는 언제나 모든 요소를 ​​반복합니다.

메모리와 문자열을 비교하는 C 라이브러리의 기능은 사용하기 매우 어렵습니다.

당신은 쓰기:

char *str = "Hello, world!";

if (strcmp(str, "Hello, world!") == 0) {
    /* ... */
}

또는

char *str = "Hello, world!";

if (!strcmp(str, "Hello, world!")) {
    /* ... */
}

확인하려면 str ~를 가리키다 "Hello, world".나는 개인적으로 이 두 솔루션이 모두 매우 보기 흉하고 혼란스러워 보인다고 생각합니다(특히 !strcmp(...)).

다음은 문자열이나 메모리를 비교해야 할 때 일부 사람들(나 포함)이 사용하는 두 가지 깔끔한 매크로입니다. strcmp/memcmp:

/* Compare strings */
#define STRCMP(A, o, B) (strcmp((A), (B)) o 0)

/* Compare memory */
#define MEMCMP(A, o, B) (memcmp((A), (B)) o 0)

이제 다음과 같은 코드를 작성할 수 있습니다.

char *str = "Hello, world!";

if (STRCMP(str, ==, "Hello, world!")) {
    /* ... */
}

여기에 의도가 훨씬 더 명확해졌습니다!

이는 함수가 수행할 수 없는 작업에 매크로가 사용되는 경우입니다.매크로는 기능을 대체하는 데 사용되어서는 안 되지만 다른 용도로도 유용합니다.

귀하의 질문에 대한 의견을 감안할 때, 당신은 완전히 이해하지 못할 수도 있습니다. 함수를 호출하면 상당한 양의 오버 헤드가 수반 될 수 있다는 것입니다. 매개 변수와 키 레지스터는 도중에 스택에 복사되어야하며, 나가는 길에 스택은 풀어야합니다. 이것은 특히 오래된 인텔 칩에서 해당되었습니다. 매크로는 프로그래머가 함수의 추상화를 유지하도록하지만 (거의) 기능 호출의 비용이 많이 드는 오버 헤드를 피했습니다. 인라인 키워드는 자문이지만 컴파일러가 항상 올바르게 얻을 수는 없습니다. 'C'의 영광과 위험은 일반적으로 컴파일러를 의지에 구부릴 수 있다는 것입니다.

빵과 버터에서, 일상적인 응용 프로그램은 이러한 종류의 미세 최적화 (기능 호출을 피하기)를 프로그래밍하는 일상적인 응용 프로그램은 일반적으로 쓸모가 없지만 운영 체제의 커널에서 불리는 시간-중요 함수를 작성하는 경우 큰 차이를 만들 수 있습니다.

일반 함수와 달리 매크로에서 제어 흐름 (경우, ...)을 수행 할 수 있습니다. 예는 다음과 같습니다.

#include <stdio.h>

#define Loop(i,x) for(i=0; i<x; i++)

int main(int argc, char *argv[])
{
    int i;
    int x = 5;
    Loop(i, x)
    {
        printf("%d", i); // Output: 01234
    } 
    return 0;
} 

코드를 인화하고 기능 호출 오버 헤드를 피하는 데 좋습니다. 많은 장소를 편집하지 않고 나중에 동작을 변경하려는 경우 사용합니다. 복잡한 것들에는 유용하지 않지만 인라인으로 원하는 간단한 코드 라인의 경우 나쁘지 않습니다.

C 전 처리기의 텍스트 조작을 활용하여 하나는 다형성 데이터 구조와 동등한 C를 구성 할 수 있습니다. 이 기술을 사용하여 특정 구현의 세부 사항이 아니라 C 구문을 활용하기 때문에 모든 C 프로그램에서 사용할 수있는 원시 데이터 구조의 신뢰할 수있는 도구 상자를 구성 할 수 있습니다.

데이터 구조 관리를 위해 매크로를 사용하는 방법에 대한 자세한 설명은 여기에 제공됩니다. http://multi-core-dump.blogspot.com/2010/11/interesting-us-of-c-macros-polymorphic.html

매크로를 사용하면 복사 한 조각을 제거 할 수 있습니다.

예를 들어 (실제 코드, VS 2010 컴파일러의 구문) :

for each (auto entry in entries)
{
        sciter::value item;
        item.set_item("DisplayName",    entry.DisplayName);
        item.set_item("IsFolder",       entry.IsFolder);
        item.set_item("IconPath",       entry.IconPath);
        item.set_item("FilePath",       entry.FilePath);
        item.set_item("LocalName",      entry.LocalName);
        items.append(item);
    }

이곳은 같은 이름의 필드 값을 스크립트 엔진으로 전달하는 곳입니다. 이게 복사한가요? 예. DisplayName 스크립트의 문자열 및 컴파일러의 필드 이름으로 사용됩니다. 그게 나쁘니? 예. 리팩터를 리팩터링하고 이름을 바꾸는 경우 LocalName 에게 RelativeFolderName (내가 한 것처럼) 그리고 문자열과 똑같이하는 것을 잊어 버린다. 별도의 스크립트 파일이지만 스크립트가 직렬화에 사용되는 경우 100% 버그가됩니다).

이를 위해 매크로를 사용하는 경우 버그를위한 공간이 없습니다.

for each (auto entry in entries)
{
#define STR_VALUE(arg) #arg
#define SET_ITEM(field) item.set_item(STR_VALUE(field), entry.field)
        sciter::value item;
        SET_ITEM(DisplayName);
        SET_ITEM(IsFolder);
        SET_ITEM(IconPath);
        SET_ITEM(FilePath);
        SET_ITEM(LocalName);
#undef SET_ITEM
#undef STR_VALUE
        items.append(item);
    }

불행히도 이것은 다른 유형의 버그를위한 문을 열어줍니다. 매크로를 쓰는 오타를 만들 수 있으며 컴파일러가 모든 전처리를 따르는 모습을 보여주지 않기 때문에 버릇없는 코드를 볼 수 없습니다. 다른 사람이 같은 이름을 사용할 수 있습니다. #undef). 따라서 현명하게 사용하십시오. 복사 된 코드 (함수와 같은)를 제거하는 또 다른 방법이 보이면 그 방식을 사용하십시오. 매크로로 복사 된 코드를 제거하는 것이 결과 가치가 없다는 것을 알 수 있다면 복사 된 코드를 유지하십시오.

명백한 이유 중 하나는 매크로를 사용하여 코드가 컴파일 시간에 확장되고 통화 오버 헤드없이 의사 기능을 받기 때문입니다.

그렇지 않으면, 당신은 또한 상징적 상수에 사용할 수 있으므로 하나의 작은 것을 변경하기 위해 여러 장소에서 동일한 값을 편집 할 필요가 없습니다.

macros .. 당신의 &#(*$ & compiler가 무언가를 거부 할 때.

그것은 동기 부여 포스터 여야합니다.

진지하게, Google 전처리 학대 (비슷한 SO 질문을 #1 결과와 볼 수 있습니다). Assert ()의 기능을 넘어서는 매크로를 작성하는 경우 일반적으로 컴파일러가 실제로 비슷한 기능을 인화하는지 확인하려고합니다.

다른 사람들은 조건부 편집에 #if를 사용하는 것에 대해 논쟁 할 것입니다.

if (RUNNING_ON_VALGRIND)

보다는

#if RUNNING_ON_VALGRIND

.. 디버깅 목적으로, debugger에서 if ()를 볼 수 있지만 #if는 볼 수 없기 때문에. 그런 다음 우리는 #ifdef vs #if로 뛰어 들었습니다.

10 줄의 코드 미만인 경우 인라인을 사용하십시오. 인쇄 할 수 없다면 최적화하십시오. 기능이 너무 어리석은 경우 매크로를 만드십시오.

나는 매크로의 열렬한 팬이 아니며 현재의 작업을 기반으로 C를 더 이상 쓰는 경향이 없지만, 이와 같은 것이 편리합니다.

#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))

이제 나는 몇 년 동안 그런 글을 쓰지 않았지만, '기능'과 같은 '기능'은 내 경력 초기에 유지 한 코드 전체에있었습니다. 확장이 편리한 것으로 간주 될 수 있다고 생각합니다.

나는 매크로와 같은 기능과 관련하여 이것을 언급하는 사람을 보지 못했습니다.

#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))

일반적으로 필요하지 않은 경우 매크로 사용을 피하는 것이 좋습니다. 여러 가지 이유로 가독성이 주요 관심사입니다. 그래서:

기능을 언제 사용해야합니까?

더 읽기 쉬운 대안이 있기 때문에 거의 절대로 inline, 보다 https://www.greenend.org.uk/rjk/tech/inline.html또는 http://www.cplusplus.com/articles/2lywvcm9/ (두 번째 링크는 C ++ 페이지이지만 포인트는 내가 아는 한 C 컴파일에 적용 할 수 있습니다).

이제 약간의 차이점은 매크로가 사전 프로세서에 의해 처리되고 인라인이 컴파일러에 의해 처리되지만 요즘에는 실질적인 차이가 없습니다.

이것들을 사용하는 것이 언제 적절합니까?

작은 기능 (2 ~ 3 개의 라이너 최대). 목표는 매크로 (및 인라인 함수)와 같은 함수 (인라인 함수)와 같은 함수와 같은 기능 (또는 인라인의 경우 컴파일)이며 메모리에 사는 실제 기능이 아니기 때문에 프로그램의 실행 시간 동안 일부 이점을 얻는 것입니다. 따라서 기능 호출 오버 헤드가 없습니다 (링크 된 페이지의 자세한 내용).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top