C 매크로는 무엇에 유용한가?
나는 C를 조금 썼고, 그것이 무엇을 하고 있는지 대강 알 수 있을 정도로 잘 읽을 수 있지만 매크로에 부딪칠 때마다 완전히 나를 던져버렸다.나는 결국 매크로가 무엇인지 기억하고 읽으면서 머릿속으로 그것을 대체해야 한다.직관적이고 이해하기 쉬운 것들이 항상 작은 미니 기능들 같았는데 왜 기능들만이 아니었는지 늘 궁금했다.
나는 전처리장치에서 디버그나 크로스 플랫폼 빌드를 위해 다른 빌드 유형을 정의해야 할 필요성은 이해할 수 있지만, 임의의 대체물을 정의하는 능력은 이미 어려운 언어를 더 이해하기 어렵게 만드는 데만 유용한 것 같다.
왜 이렇게 복잡한 전처리가 C에게 도입되었는가?그리고 만약 #debug 스타일 조건부 컴필레이션이라면 왜 그것이 여전히 단순한 목적 이외의 용도로 사용되는지 이해할 수 있는 사용의 예가 누구라도 있는가?
편집:
여러 개의 답을 읽었는데도 여전히 이해가 안 돼.가장 흔한 대답은 인라인 코드다.인라인 키워드가 실행되지 않으면 실행하지 않을 타당한 이유가 있거나 구현을 수정해야 한다.나는 왜 "정말 인라인 이 코드"를 의미하는 전혀 다른 메커니즘이 필요한지 이해할 수 없다. (인라인 인라인 앞에 쓰여진 코드 형태와 마찬가지로)나는 또한 "기능에 넣기엔 너무 어리석다면"이라고 언급된 생각을 이해할 수 없다.확실히 입력을 하고 출력을 내는 코드는 함수에 넣는 것이 가장 좋다.나는 내가 C를 쓰는 것의 미시적 최적화에 익숙하지 않기 때문에 그것을 얻지 못하고 있다고 생각하지만, 전처리는 단지 몇 가지 간단한 문제들에 대한 복잡한 해결책처럼 느낀다.
나는 결국 매크로가 무엇인지 기억하고 읽으면서 머릿속으로 그것을 대체해야 한다.
그것은 매크로의 이름에 대해 좋지 않은 영향을 미치는 것 같다.가 리리라면 모리도 될아도 것 .log_function_entry()
매크로의
직관적이고 이해하기 쉬운 것들이 항상 작은 미니 기능들 같았는데 왜 기능들만이 아니었는지 늘 궁금했다.
일반적으로 일반적인 매개 변수로 작동할 필요가 없는 한 그렇게 해야 한다.
#define max(a,b) ((a)<(b)?(b):(a))
이든 어어 유형이 이 with이<
교환원의
매크로를 사용하면 소스 파일의 기호를 사용하여 작업을 수행할 수 있다.즉, 새 변수 이름을 만들거나 매크로가 있는 소스 파일과 라인 번호를 참조할 수 있다.
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
및 줄 가드가 참일 경우 메시지를 인쇄한 파일 및 줄 번호와 함께 메시지를 출력한다.함수 호출이었다면, 당신이 호출한 파일과 줄을 모르고, a를 사용했을 것이다.vaprintf
일이 좀 더 많을 거야
이 발췌문은 그 문제에 대한 나의 견해를 몇 가지 방법으로 비교함으로써 요약한다.C
매크로를 사용하고, 매크로를 구현하는 방법D
.
다음 시간
C
발명되었고 컴파일러 기술은 원시적이었다.텍스트 매크로 전처리기기를 프런트 엔드에 설치하는 것은 많은 강력한 기능을 추가하는 간단하고 쉬운 방법이었다.프로그램의 규모와 복잡성의 증가는 이러한 특징들이 많은 본질적인 문제들을 수반한다는 것을 보여준다.D
전처리는 없다D
동일한 문제를 해결하기 위해 더 확장 가능한 수단을 제공한다.
매크로스
전처리기 매크로에 강력한 기능과 유연성을 추가C
그러나 그들은 단점을 가지고 있다.
- 매크로는 범위 개념이 없다. 매크로는 정의 지점에서 소스의 끝까지 유효하다.그들은 .h 파일, 중첩된 코드 등을 가로지르고 있다.언제
#include
하지 않은 수만 줄의 매크로 정의에 따라 의도하지 않은 매크로 확장을 방지하는 것은 문제가 된다. - 매크로는 디버거에게 알려져 있지 않다.상징적인 데이터로 프로그램을 디버깅하려고 하는 것은 매크로 자체가 아니라 매크로 확장에 대해서만 아는 디버거에 의해 훼손된다.
- 매크로는 이전의 매크로 변경은 임의로 토큰을 재실행할 수 있기 때문에 소스 코드의 토큰화가 불가능하게 만든다.
- 매크로의 순수 텍스트 기반은 임의적이고 일관되지 않은 사용으로 이어져 매크로를 사용하는 코드를 쉽게 만든다.(이 문제를 해결하기 위한 일부 시도가 에 템플릿과 함께 도입됨)
C++
.) - 매크로는 헤더 파일 주변의 "wrappers"와 같은 언어 표현 능력의 결함을 보충하기 위해 여전히 사용된다.
다음은 매크로의 일반적인 용도와 해당 기능을 열거한 것이다.
리터럴 상수 정의:
그
C
전처리기 방식#define VALUE 5
그
D
길const int VALUE = 5;
값 또는 플래그 목록 만들기:
그
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;
함수 호출 규칙 설정:
그
C
전처리기 방식#ifndef _CRTAPI1 #define _CRTAPI1 __cdecl #endif #ifndef _CRTAPI2 #define _CRTAPI2 __cdecl #endif int _CRTAPI2 func();
그
D
길호출 규약은 블록 단위로 지정할 수 있으므로 모든 기능에 대해 변경할 필요가 없음:
extern (Windows) { int onefunc(); int anotherfunc(); }
단순 일반 프로그래밍:
그
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;}
...
당신이 원한다고 해도, 당신은 기능을 과부하할 수 없기 때문이다.
그리고 (또한 매크로 언어의 일부인)을 포함하는 조건부 컴파일 및 파일은 말할 것도 없고...
나는 이미 말한 것을 덧붙일 것이다.
매크로는 텍스트 대체에 작용하기 때문에 기능을 사용할 수 없는 매우 유용한 일들을 할 수 있다.
매크로가 매우 유용할 수 있는 몇 가지 사례:
/* 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!")) {
/* ... */
}
여기 의도가 훨씬 더 명확하다!
매크로가 기능으로는 달성할 수 없는 것에 사용되는 경우들이다.매크로는 기능을 대체하기 위해 사용되어서는 안 되지만 다른 좋은 용도가 있다.
일반적인 기능과 달리 매크로에서 제어 흐름(만약에, 반면, 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;
}
From Computer Dumnities:
UNIX용 프리웨어 게임 프로그램에서 발췌한 이 코드를 본 적이 있다.
/*
* 비트 값.
*/
B#Define BIT_0 1
B#Define BIT_1 2
B#Define BIT_2 4
B#Define BIT_3 8
#Define BIT_4 16
B#Define BIT_5 32
B#Define BIT_6 64
B#Define BIT_7 128
B#Define BIT_8256
B#Define BIT_9 512
B#Define BIT_10 1024
#Define BIT_11 2048
#Define BIT_12 4096
B#Define BIT_13 8192
B#Define BIT_14 16384
#Define BIT_15 32768
BIT_16 의 BIT_16 65536
BIT_17 의 BIT_17 131072
B#Define BIT_18 262144
B#Define BIT_19 524288
B#Define BIT_20 1048576
B#Define BIT_21 2097152
B#Define BIT_22 4194304
B#Define BIT_23 8388608
B#Define BIT_24 16777216
B#Define BIT_25 33554432
BIT_26 의 BIT_26 67108864
B#Define BIT_27 134217728
B#Define BIT_28 268435456
B#Define BIT_29 536870912
B#Define BIT_30 1073741824
B#Define BIT_31 2147483648이를 달성하는 훨씬 쉬운 방법은 다음과 같다.
B#Define BIT_0 0x00000001
B#Define BIT_1 0x00000002
B#Define BIT_2 0x00000004
B#Define BIT_3 0x00000008
#Define BIT_4 0x00000010
...
B#Define BIT_28 0x10000000
B#Define BIT_29 0x20000000
B#Define BIT_30 0x40000000
B#Define BIT_31 0x80000000더 쉬운 방법은 컴파일러가 다음과 같은 계산을 하도록 하는 것이다.
B#Define BIT_0(1)
B#Define BIT_1 (1< 1)
B#Define BIT_2(1< 2)
B#Define BIT_3(1< 3)
BIT_4 (1< 4)
...
B#Define BIT_28 (1< 28)
B#Define BIT_29 (1< 29)
B#Define BIT_30 (1< 30)
B#Define B IT_31 (1< 31)그런데 왜 32개의 상수를 규정하는 수고를 다 하는 것일까?C언어에는 파라미터화된 매크로도 있다.필요한 것은 다음과 같다:
#BIT(x) (1< (x)))
어쨌든, 나는 원래 코드를 쓴 사람이 계산기를 썼는지 아니면 그냥 전부 종이로 계산했는지 궁금하다.
그것은 매크로를 사용할 수 있는 한 가지 방법일 뿐이다.
코드 입력 및 함수 호출 오버헤드 피하기에 좋다.많은 장소를 편집하지 않고 나중에 동작을 변경하려는 경우 사용하는 것뿐만 아니라복잡한 것에는 유용하지 않지만, 인라인으로 하고 싶은 간단한 코드의 경우 나쁘지 않다.
매크로는 컴파일 시간 동안 다른 사람이 프로그램 동작을 수정할 수 있도록 한다.다음을 고려하십시오.
- C 상수는 개발 시 프로그램 동작을 수정하는 것을 허용한다.
- C 변수 실행 시 프로그램 동작을 수정할 수 있음
- C 매크로 컴파일 시 프로그램 동작을 수정할 수 있음
컴파일 시간에 미사용 코드는 바이너리로 들어가지 않으며, 매크로 전처리와 통합된 한 빌드 프로세스가 값을 수정할 수 있다는 것을 의미한다.예: ARCH=arm 만들기(매크로 정의 전달을 cc -DARCH=arm으로 가정)
간단한 예: (glibc limits.h에서 긴 값 중 가장 큰 값을 정의)
#if __WORDSIZE == 64
#define LONG_MAX 9223372036854775807L
#else
#define LONG_MAX 2147483647L
#endif
32비트 또는 64비트에 대해 컴파일하는 경우 컴파일 시간에 확인(#define __WORDSIZE 사용)멀티빌리브 툴체인에서는 매개 변수 -m32 및 -m64를 사용하면 비트 크기가 자동으로 변경될 수 있다.
(POSIX 버전 요청)
#define _POSIX_C_SOURCE 200809L
컴파일 시간 중 요청 POSIX 2008 지원.표준 라이브러리는 많은 (호환 불가능한) 표준을 지원할 수 있지만, 이 정의와 함께 올바른 기능 프로토타입(예: getline(), no get() 등)을 제공한다.예를 들어, 라이브러리가 표준을 지원하지 않을 경우, 실행 중에 충돌하는 대신 컴파일 시간 동안 오류가 발생할 수 있다.
(하드 코드화된 경로)
#ifndef LIBRARY_PATH
#define LIBRARY_PATH "/usr/lib"
#endif
컴파일 시간 동안 하드코드 디렉터리를 정의하십시오.예를 들어 -DIBRARY_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 언어의 기본 구성만 사용할 수 있다. 명목상 C를 쓰는 동안 자신의 데이터 구조와 코드 구성(클래스 및 템플릿 포함)을 정의할 수 있다!
전처리기 매크로는 실제로 컴파일 시간에 실행되는 튜링-완전한 언어를 제공한다.이에 대한 인상적인(그리고 약간 두려운) 예시 중 하나는 C++ 쪽에서 끝난다: Boost Preprocessor 라이브러리는 C99/C++98 전프로세서를 사용하여 안전한 프로그래밍 구조를 구축(상대적으로)하고 C+++가 입력하는 모든 기본 선언과 코드로 확장된다.
실제로, 나는 전처리기 프로그래밍을 마지막 수단으로 추천한다. 더 안전한 언어로 높은 수준의 구조를 사용할 수 있는 권한이 없을 때.하지만 가끔 등을 벽에 기대고 족제비들이 가까이 다가오면 어떻게 할 수 있는지 아는 것은 좋은 일이다...!
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
스크립트의 문자열과 컴파일러의 필드 이름으로 사용된다.심하게 아픈가요?네. 리팩터링하면 코드와 이름을 바꾸면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
그러니 현명하게 사용하라.복사 붙여넣은 코드(예: 함수)를 제거하는 다른 방법이 있는 경우 이 방법을 사용하십시오.매크로와 함께 복사 붙여넣은 코드를 제거할 가치가 없는 경우 복사 붙여넣은 코드를 유지하십시오.
질문의 코멘트를 고려할 때, 함수를 호출하는 것은 상당한 양의 오버헤드를 수반할 수 있다는 점을 충분히 인식하지 못할 수 있다.매개변수와 키 레지스터는 들어오는 도중에 스택에 복사해야 할 수 있으며, 나가는 도중에 스택이 풀릴 수 있다.이것은 특히 오래된 인텔 칩에 적용되었다.매크로스는 프로그래머가 함수의 추상화(대부분의)를 유지하도록 했지만 함수 호출의 비용이 많이 드는 오버헤드는 피했다.인라인 키워드는 권고사항이지만 컴파일러가 항상 올바르게 인식하지는 않을 수 있다.'C'의 영광과 위험은 보통 컴파일러를 뜻대로 구부릴 수 있다는 것이다.
여러분의 빵과 버터에 있어서, 이런 종류의 미세 최적화(안호함수 호출)를 매일 하는 애플리케이션 프로그래밍은 일반적으로 더 나쁘고 쓸모없지만, 만약 여러분이 운영체제의 커널에 의해 불리는 시간에 중요한 함수를 쓰고 있다면, 그것은 엄청난 차이를 만들 수 있다.
매크로(및 사전 프로세서)는 C의 초기부터 발생한다는 점을 기억하십시오.그들은 인라인 '기능'을 할 수 있는 유일한 방법이었고(물론 인라인이라는 것이 매우 최근의 키워드이기 때문), 여전히 인라인으로 채워질 무언가를 강제할 수 있는 유일한 방법이다.
또한, 컴파일할 때 문자열 상수에 파일과 줄을 삽입하는 것과 같은 트릭을 할 수 있는 유일한 방법은 매크로다.
요즘에는 매크로만이 유일한 방법이었던 많은 것들이 새로운 메커니즘을 통해 더 잘 처리되고 있다.하지만 그들은 여전히 때때로 그들의 자리를 가지고 있다.
분명한 이유 중 하나는 매크로를 사용함으로써 컴파일 시간에 코드가 확장되어 통화 오버헤드 없이 사이비 함수 호출이 가능하기 때문이다.
그렇지 않으면 여러 곳에서 동일한 값을 편집하여 하나의 작은 것을 변경할 필요가 없도록 기호 상수에도 사용할 수 있다.
매크로스..당신의 &#(*$&) 컴파일러가 무언가를 인라인으로 보내는 것을 거절할 때를 위해서입니다.
그건 동기부여 포스터가 될거야, 안그래?
심각하게도, 구글 전처리기 남용 (1위 결과와 유사한 SO 질문을 볼 수 있다.)주장()의 기능성을 뛰어넘는 매크로를 쓰고 있다면, 나는 보통 내 컴파일러가 실제로 비슷한 함수에 인라인으로 접속할 수 있는지 알아보려고 한다.
다른 사람들은 조건부 편찬을 위해 #를 사용하는 것에 반대할 것이다.고객이 원하는 것은 다음과 같다.
if (RUNNING_ON_VALGRIND)
보다는
#if RUNNING_ON_VALGRIND
..디버깅을 위해 ifduck은 볼 수 있지만 #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개 라이너)의 경우.매크로(및 인라인 함수)와 같은 기능은 사전 처리(또는 인라인인 경우 컴파일) 중에 수행되는 코드 교환이며 메모리에 상주하는 실제 기능이 아니므로, 프로그램 실행 시간 동안 어느 정도 이점을 얻는 것이 목표다.
참조URL: https://stackoverflow.com/questions/653839/what-are-c-macros-useful-for
'programing' 카테고리의 다른 글
NuxtJs 경로에서 *(아스터스크)를 사용하는 방법? (0) | 2022.04.27 |
---|---|
vuex를 사용하여 데이터 업데이트 (0) | 2022.04.27 |
한 구조물을 다른 구조물에 복사 (0) | 2022.04.27 |
상속과 구성의 차이 (0) | 2022.04.27 |
C의 함수에서 여러 값을 반환하려면 어떻게 해야 하는가? (0) | 2022.04.27 |