ProgramingTip

C 매크로는 무엇에 유용합니까?

bestdevel 2020. 10. 26. 08:24
반응형

C 매크로는 무엇에 유용합니까?


나는 약간의 C를 썼고 그것이 무엇을하고 있는지에 대한 일반적인 아이디어를 얻을 수있을만큼 충분히 읽을 수있는 매크로를 만날 때마다 그것은 나를 완전히 던졌습니다. 결국 매크로가 무엇인지 기억하고 읽는 동안 머릿속으로 대체해야합니다. 쉬운이고 이해하기 쉬운 내가 만난 것들은 항상 작은 미니 기능 같았 기 때문에 왜 그런 단순한 기능이 아닌지 항상 궁금했습니다.

전 처리기에서 디버그 또는 크로스 플랫폼 빌드에 대해 서로 다른 빌드 유형을 정의 할 수 있습니다. 임의의 대체 기능을 사용할 수 있습니다. 이미 어려운 언어를 이해하기 더 어렵게 데에만 사용할 수 있습니다.

왜 그렇게 복잡한 전처리 기가 C에 도입 되었습니까? 그리고 누군가 #debug 스타일 조건부에서는 단순한 경우 이외의 목적으로 여전히 사용되는 것처럼 보이는 이유를 사용하는 사용 예제가?

편집하다 :

여러 답변을 읽은 후에도 여전히 이해하지 못합니다. 가장 일반적인 대답은 인라인 코드입니다. 인라인 키워드가이를 합당한 이유가 구현에 수정이 필요하지 않습니다. 나는 다른 것 외에 필요한 이유를 이해하지 못합니다. 이것은 "이 코드를 실제로 인라인"의미입니다 (인라인 이전에 작성되는 코드를 제외하고). 나는 또한 "함수에 넣기에 너무 어리석은 경우"라고 언급 한 아이디어를 이해하지 못합니다. 확실히 입력을 받아 출력을 생성하는 코드는 함수에 넣는 것이 가장 좋습니다. 나는 C 작성의 마이크로 최적화에 익숙하지 않기 때문에 그것을 얻지 못할 수도 있다는 생각 하지만 전처리 기는 몇 가지 간단한 문제에 대한 복잡한 해결 방법이 있습니다.


나는 결국 매크로가 무엇인지 기억하고 읽는 동안 내 머릿속으로 대체해야한다.

그것은 매크로의 이름을 제대로 반영하지 않을 것입니다. log_function_entry()매크로 라면 전처리기를 에뮬레이트 할 필요가 처리 됩니다.

쉽게이고 이해하기 쉬운 내가 만난 것들은 항상 작은 미니 기능과 같았 기 때문에 왜 기능이 기능이 아닌지 궁금했습니다.

일반적으로 일반 매개 변수에 대해 작동 할 필요가없는 한 그렇게해야합니다.

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

<연산자 가있는 모든 유형에서 작동합니다.

기능뿐 아니라 매크로를 사용하면 소스 파일의 기호를 사용하여 작업을 수행 할 수 있습니다. 즉, 새 변수 이름을 만들거나 매크로가있는 소스 파일과 줄 번호를 참조 할 수 있습니다.

C99에서 매크로를 사용하면 printf와 같은 가변 함수를 호출 할 수도 있습니다.

#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매크로가 사용되는 여러 방법 과 .NET에서 구현하는 방법을 비교하여 문제에 대한 내 견해를 거의 요약합니다 D.

DigitalMars.com에서 복사

C발명 증권 때 컴파일러 기술은 원시적이었다. 간단한 엔드에 텍스트 매크로 전처리기를 설치하는 것은 많은 기능을 추가하는 간단하고 쉬운 방법. 고유 한 문제가 있습니다. D전처리 기가 없습니다. 그러나 D동일한 문제를 해결하기 위해 더 확장 가능한 수단을 제공합니다.

매크로

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

  • 매크로에는 범위 개념이 없습니다. 정의 지점부터 소스 끝까지 유효합니다. 그들 .h 파일, 중첩 된 코드 등을 가로 질러 #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 위에있는 프로그래밍 언어 (더 간단한 언어를 수행하는 데 시간에 메타 프로그래밍을 수행하는 데 유용합니다. 즉, 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 매크로를 사용하면 시간에 프로그램을 사용할 수 있습니다.

시간에 사용하지 않는 코드는 바이너리로 이동하지 않고 매크로 전처리 기와 통합되어있는 한 빌드 프로세스가 값이 있음을 의미합니다. 예 : make ARCH = arm (전달 매크로 정의를 cc -DARCH = arm로 가정)

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

#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 (), get () 없음 등). 라이브러리가 표준을 지원하지 않는 경우, 예를 들어 실행 중에 충돌하는 대신에 시간 동안 #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의 초창기에서 나온 것임을 기억하십시오. 그들은 인라인 '함수'를 수행하는 유일한 방법이었습니다 (물론 인라인은 매우 최근의 키워드이기 때문입니다). 인라인 될 내용을 강제하는 유일한 방법입니다.

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

요즘에는 매크로가 유일한 방법이 많은 것들이 더 잘 처리됩니다. 그러나 여전히 그들은 자신의 자리를 가지고 있습니다.


효율성 및 조건부 설치를위한 인라인 외에도 매크로를 사용하여 저수준 C 코드의 추상화 수준을 사용할 수 있습니다. C는 메모리 및 리소스 관리의 핵심적인 세부 사항과 정확한 데이터 레이아웃에서 실제로 사용자를 배치하지 않고 매우 관리를 형태의 정보 숨김 및 관리 시스템 기타를 지원합니다. 매크로를 사용하면 더 이상 C 언어의 기본 구조 만 사용하는 것에 국한되지 않습니다. 명목상 C를 작성하면서 자신의 데이터 구조와 코딩 구조 (클래스 및 템플릿 포함!)를 정의 할 수 있습니다.

전 처리기 매크로는 실제 시간에 실행 되는 Turing-complete 언어를 제공합니다 . 이것에 대한 인상적인 (그리고 약간 무서운) 예제 중 하나는 C ++ 측에서 끝났습니다. Boost Preprocessor 라이브러리는 C99 / C ++ 98 전처리기를 사용하여 (상대적으로) 안전한 프로그래밍 구조를 빌드 한 다음 기본 선언 및 코드로 확장됩니다. C 든 C ++ 든 입력합니다.

실제로는 안전한 언어로 높은 수준의 구조를 사용할 수없는 경우 마지막 수단으로 전 처리기 프로그래밍을 고려하는 것이 좋습니다. 하지만 등이 벽에 닿아 있고 족제비가 닫히면 무엇을 할 수 있는지 아는 것이 좋습니다 ...!


에서 컴퓨터 어리 석음 :

이 코드는 많은 UNIX 용 프리웨어 게임 프로그램에서 발췌 한 것을 보았습니다.

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

이를 달성하는 훨씬 쉬운 방법은 다음과 가능합니다.

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

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

#define 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)
# BIT_29 정의 (1 << 29)
# BIT_30 정의 (1 << 30)
# BIT_31 정의 (1 << 31)

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

#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;
}

여기서 다른 프로그래머가 adecleration에 5 개의 요소를 더 추가해도 상관 없습니다 . for-loop는 항상 모든 요소를 ​​반복합니다.

메모리와 공유를 비교하는 C 라이브러리의 함수는 사용하는 매우 추합니다.

당신은 쓰기 :

char *str = "Hello, world!";

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

또는

char *str = "Hello, world!";

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

str비용 지 확인 클릭 "Hello, world". 저는 개인적 으로이 두 솔루션이 매우 추하고 혼란스러워 보인다고 생각합니다 ( !strcmp(...)).

다음은 일부 사람들 (I 포함)이 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'의 영광과 위험은 일반적으로 컴파일러를 원하는대로 구부릴 수 있다는 것입니다.

빵과 버터에서 이러한 종류의 마이크로 최적화 (함수 호출 방지)는 일반적으로 더 나쁘고 쓸모가 없지만 운영 체제의 커널에서 호출하는 시간이 중요한 함수를 작성하는 경우 큰 차이를 만들 수 있습니다.


일반 함수와 달리 매크로에서 제어 흐름 (if, while, for, ...)을 수행 할 수 있습니다. 예를 들면 다음과 같습니다.

#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-use-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스크립트의 문자열과 컴파일러의 필드 이름으로 사용됩니다. 그게 나쁜가요? 예. 코드를 리팩터링하고 이름 LocalNameRelativeFolderName(내가했던 것처럼) 문자열로 똑같이하는 것을 잊는 경우 (내가했던 것처럼) 스크립트는 예상하지 못한 방식으로 작동합니다 (사실, 내 예에서는 별도의 스크립트 파일에서 필드 이름을 바꾸는 것을 잊었습니까? 그러나 스크립트가 직렬화에 사용되는 경우 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). 따라서 현명하게 사용하십시오. 복사하여 붙여 넣은 코드 (예 : 함수)를 제거하는 다른 방법이 있다면 그 방법을 사용하십시오. 매크로로 복사하여 붙여 넣은 코드를 제거하는 것이 결과의 가치가 없다는 것을 알게되면 복사하여 붙여 넣은 코드를 유지하십시오.


분명한 이유 중 하나는 매크로를 사용하면 코드가 컴파일 타임에 확장되고 호출 오버 헤드없이 의사 함수 호출을 얻을 수 있다는 것입니다.

그렇지 않으면 기호 상수에도 사용할 수 있으므로 작은 하나를 변경하기 위해 여러 위치에서 동일한 값을 편집 할 필요가 없습니다.


매크로 .. & # (* $ & 컴파일러가 인라인을 거부 할 때 사용합니다.

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

진지하게 말하면 Google 전 처리기 남용입니다 (# 1 결과와 유사한 SO 질문을 볼 수 있음). assert ()의 기능을 넘어서는 매크로를 작성하는 경우 일반적으로 컴파일러가 실제로 유사한 함수를 인라인하는지 확인하려고합니다.

다른 사람들은 조건부 컴파일을 위해 #if를 사용하는 것에 반대 할 것입니다.

if (RUNNING_ON_VALGRIND)

보다는

#if RUNNING_ON_VALGRIND

.. 디버깅 목적으로 if ()는 볼 수 있지만 디버거에서는 #if를 볼 수 없습니다. 그런 다음 #ifdef 대 #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 개의 라이너). 매크로 (및 인라인 함수)와 같은 함수는 사전 처리 (또는 인라인의 경우 컴파일) 중에 수행되는 코드 대체이며 메모리에있는 실제 함수가 아니기 때문에 목표는 프로그램 실행 시간 동안 일부 이점을 얻는 것입니다. 따라서 함수 호출 오버 헤드가 없습니다 (자세한 내용은 링크 된 페이지 참조).

참고 URL : https://stackoverflow.com/questions/653839/what-are-c-macros-useful-for

반응형