내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
C 언어에는 몇 가지 설정이 있습니다.사전 정의된 기호, 직접 사용할 수 있으며 사전 정의된 기호는 다음과 같습니다.在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
예:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
작업 결과:
VS는 ANSI C(표준 C)를 완벽하게 지원하지 않는다는 점을 여기서 언급하고 싶습니다. gcc gccg참조 ANSI C(표준 C) 지원
기본 구문:
# define name stuff
예를 들어:
#define MAX 100
#define reg register // 为 register 这个关键字创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写 case 语句的时候自动吧 break 写上
//如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)
#define DEBUG_PRINT printf("file:%stline:%dt
date:%sttime:%sn" ,
__FILE__,__LINE__ ,
__DATE__,__TIME__ )
- 두 번째 문장은 게으름인데 왜요?
- 세 번째 문장 에 대한 에 대한에프또는 회보
初始化、判断、调整都可以省略
, 그러나 판단이 생략되면 판단 조건이 항상 참이라는 뜻, 즉무한 루프- 네 번째 게임에서는 이 작업을 수행하지 않는 것이 가장 좋습니다. 쉽게 문제가 발생할 수 있습니다.
- 다섯 번째 문장줄 연속 문자분기 후 문제를 방지하는 것이 그 본질입니다.
转义
뒤쪽에回车符
, 캐리지 리턴이 더 이상 캐리지 리턴이 아닙니다.줄 연속 문자 뒤에는 아무 것도 올 수 없습니다.“”
Enter를 누르기만 하면 됩니다. 그렇지 않으면 다음 코드 줄이 계속되지 않습니다.
이제 문제가 발생합니다. #을 사용하세요. 정의하다 정의하다디이자형에프~에이자형 식별자를 정의할 때 끝에 추가해야 합니까?;
?
예를 들어:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
위의 코드 플러스;
, 약간 중복되는 것처럼 보이지만 프로그램 실행에는 영향을 미치지 않습니다.
추가하는 것 같더라구요;
아니면 추가하지 마세요;
괜찮을까요?
정말 이런거야?
다음 예를 살펴보겠습니다.
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
교체 후:
printf("%dn", 1000;);
인쇄1000;
무슨 뜻인가요?
if (1)
max = 1000;
;
else
max = 1;
그 밖에 그 밖에이자형엘세 누구랑 어울릴까?
알다시피, 이건 뭔가 문제가 있어요.사용 # 정의하다 정의하다디이자형에프~에이자형 지표를 정의할 때 뒤에 추가하지 마십시오.;
# 정의하다 정의하다디이자형에프~에이자형 메커니즘에는 다음 조항이 포함됩니다.允许把参数替换到文本中
, 이 구현은 종종 호출됩니다.매크로 (마르코) (마르코)(엄마알코)또는 매크로 정의 ( definemacro ) ( define macro)(디이자형에프~에이자형엄마크로)
위의 매크로와 매크로 정의 식별자의 차이점은 다음과 같습니다.매크로에는 매개변수가 있습니다.
매크로가 선언되는 방법은 다음과 같습니다.
#define name(parament - list) stuff
그들 중 하나 매개변수 매개변수피ㅏ아르 자형~이다이자형N티 - 목록 목록엘나에스티(매개변수 목록)은 다음에 나타날 수 있는 쉼표로 구분된 기호 목록입니다. 물건 물건에스티유ff 가운데
메모: 매개변수 매개변수피ㅏ아르 자형~이다이자형N티 - 목록 목록엘나에스티(파라미터 목록)왼쪽 괄호반드시 함께 있어야 합니다 이름 이름이름이자형 옆에, 사이에 공백이 있으면 인수 목록은 다음과 같이 해석됩니다. 물건 물건에스티유ff 의 일부.
예:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
작업 결과:
보시다시피 5의 제곱이 올바르게 계산되었습니다.
그러나 실제로 위 코드에는 문제가 있습니다. 다음 코드 조각을 참조하세요.
int a = 5;
printf("%dn", SQUARE(a + 1));
작업 결과:
왜 그럴까요? 5+1의 결과는 36, 6 ∗ * ∗ 6은 36이 되어야 하는데 어떻게 11을 얻었나요?
문제는 매크로에 있습니다.宏是直接替换
, 위 코드를 직접 대체한 결과는 다음과 같습니다.
printf("%dn", a+1*a+1);
5 + 6 + 1, 결과는 당연히 11
매크로 정의의 양쪽에 괄호를 추가하면 이 문제를 쉽게 해결할 수 있습니다.
#define SQUARE(x) (x)*(x)
그렇다면 이 정의에는 문제가 없는 걸까요?다음 매크로 정의를 살펴보겠습니다.
#define DOUBLE(X) (X)+(X)
이전 문제를 피하기 위해 정의에 괄호를 사용했지만 이 매크로로 인해 새로운 오류가 발생할 수 있습니다.
int a = 5;
printf("%dn", 10 * DOUBLE(a));
작업 결과:
출력 결과는 100이 아니고 55입니다. 이유는 위와 같습니다. 우선순위 질문
해결책:
#define DOUBLE(X) ((X)+(X))
요약하자면, 매크로를 사용할 때절대로 괄호를 무시하지 마세요매크로를 사용할 때 매개변수의 연산자나 인접 연산자 간의 예상치 못한 상호 작용을 방지합니다.
매크로 정의에 매크로 매개변수가 두 번 이상 나타나는 경우 매개변수에부작용, 그러면 이 매크로를 사용할 때 위험에 처할 수 있습니다.不可预测
의 결과. 부작용은 표현식을 평가할 때 영구적인 효과입니다.
예를 들어:
x + 1; //不带副作用
x++; //带副作用
다음 MAX 매크로는 부작용이 있는 매개변수로 인해 발생하는 문제를 보여줍니다.
#define MAX(a,b) ((a) > (b) ? (a):(b))
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("x=%d, y=%d, z=%dn", x, y, z);
return 0;
}
작업 결과:
왜 그럴까요?같이 분석해보자
z = ((X++) > (y++) ? (x++) : (y++))
- 먼저 판단하십시오. 더블 엑스엑스++ 와 예와이++ 판단, 접미사이므로 ++ 판단할 때 더블 엑스엑스 5, 예와이 8, 8 > 5입니다.
- 심사 후 더블 엑스엑스 6, 예와이 9인용
- 그런 다음 실행 예와이 ++, 후위가 붙어 있으므로 ++ 결과는 9입니다.
- 그럼 계속하세요 예와이 자동 증가를 수행하고, 예와이 최종 결과는 10
우리는 할 것이다 더블 엑스엑스 그리고 예와이 매크로에 전달되면 결과가 변경되었습니다. 특히 예와이, 두 번 변경한 후 끔찍하지 않다고 말씀하셨습니다.
부작용이 있는 매개변수가 매크로에 전달되고 매개변수가 매크로에 두 번 이상 나타나는 경우 해당 매개변수의 부작용도 두 번 이상 나타납니다.
프로그램 #에서 확장 정의하다 정의하다디이자형에프~에이자형 심볼과 매크로를 정의할 때 관련된 여러 단계가 있습니다.
参数进行检查
, #이 포함되어 있는지 확인하세요. 정의하다 정의하다디이자형에프~에이자형 한정된标识符
.그렇다면 먼저 교체됩니다.被插入
매크로 매개변수 이름을 해당 값으로 대체하여 프로그램의 원래 위치로 이동합니다.#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
위 코드의 MAX는 #으로도 표현됩니다. 정의하다 정의하다디이자형에프~에이자형 한정된매크로 .지난번 검사에서 해당 매개변수 M이 교체되었습니다. 이번에는 이를 교체해야 합니다.
최대(x, 10) 최대(x, 10)중ㅏ엑스(엑스,10) 로 대체됩니다 ( ( x ) > ( 10 ) ((x) > (10)((엑스)>(10)
?
?
? ( x ) : ( 10 ) ) (x):(10))(엑스):(10))
틀림없이,宏里面嵌套宏
그것도 괜찮아
MAX(x, MAX(2, 3))
이때 먼저 매개변수에 있는 매크로를 교체한 후 전체 매크로를 교체합니다.
그러나 주목해야 할 점은 이것이다.不是递归
, 이는 다른 매크로에 대한 인수 역할을 하는 매크로일 뿐입니다.递归是宏内部又调用了宏本身
。
또한 전처리기가 #을 검색할 때 정의하다 정의하다디이자형에프~에이자형 기호를 정의할 때,문자열 상수의 내용은 검색되지 않습니다.
그게 무슨 뜻이에요?밤을 주면 이해하게 될 것입니다.
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
위의 코드에서printf("M = %d", x);
가운데 MM중 10으로 대체되지 않습니다.
위의 매크로는 두 숫자 중 더 큰 값을 찾는 데 사용됩니다. 이를 완전히 함수로 작성할 수 있습니다.
int Max(int x, int y)
{
return x > y ? x : y;
}
우리는 그것들이 모두 동일한 기능을 수행한다는 것을 발견했습니다.그러나 "두 숫자 중 더 큰 숫자 찾기" 기능의 경우 매크로를 작성하면更有优势
일부
두 가지 이유가 있습니다:
- 사용
调用函数
그리고函数返回
~의암호이 작은 계산을 실제로 수행하는 것보다 시간이 더 걸릴 수 있습니다(함수를 호출할 때).스택 프레임 생성 ).따라서 매크로 비율 기능은 프로그램에 있습니다.规模
그리고速度
그 어느 때보다 나아졌습니다- 더 중요한 것은
函数的参数必须声明类型
, 이는 해당 함수가 적절한 유형의 표현식에만 사용되도록 합니다.반대로 이 매크로는 정수, 긴 정수, 부동 소수점 등 다양한 유형에 적용할 수 있습니다.
>
비교하기 위해서.매크로의 매개변수는 다음과 같습니다.유형 독립적~의。
앞으로도 항상 매크로를 사용하게 될까요?실제로 매크로는 다음 용도로만 사용됩니다.간단한 계산, 매크로에 비해 복잡하고 대규모 작업 및 기능에는 적합하지 않습니다. 단점:
- 매크로가 사용될 때마다 매크로 정의 코드의 복사본이 프로그램에 삽입됩니다.매크로가 상대적으로 짧지 않은 한,
大幅度增加程序的长度
- 매크로는
没法调试
~의- 매크로는 유형 독립적입니다. 즉,
不够严谨
- 매크로는 작업 우선 순위 문제를 발생시켜 프로그램이
容易出错
하지만 때로는 함수가 할 수 없는 일을 매크로가 할 수도 있습니다.
예를 들어:
int* p = (int*)malloc(10 * sizeof * (int));
우리는 이런 식으로 쓰는 것을 좋아하지 않습니다 멀록 멀록엄마나는오씨 기능이 너무 번거로워서 하고 싶어요大小
그리고类型
넘겨서 공간을 열어주세요
Malloc(10, int);
함수가 이것을 할 수 있나요?아니, 왜냐면함수는 유형을 전달할 수 없습니다.
그리고 매크로는 그것을 할 수 있습니다. 왜냐하면 매크로는 그렇지 않기 때문입니다.확인하지 마세요당신의 매개변수유형~의
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
매크로와 함수의 비교:
속성 | # 정의하다 정의하다디이자형에프~에이자형매크로 정의 | 기능 |
---|---|---|
코드 길이 | 사용할 때마다 매크로 코드가 프로그램에 삽입됩니다. 매우 작은 매크로를 제외하면 프로그램 길이가 크게 늘어납니다. | 함수 코드 값은 한곳에 나타나며, 함수를 사용할 때마다 그 곳의 동일한 코드가 호출됩니다. |
실행 속도 | 더 빠르게 | 함수 호출 및 반환(스택 프레임 열기)에 추가 오버헤드가 있으므로 느린 것부터 시작하겠습니다. |
연산자 우선순위 | 매크로 매개변수는 주변의 모든 표현식의 맥락에서 평가됩니다. 괄호가 포함되지 않으면 인접한 연산자의 우선순위로 인해 예측할 수 없는 결과가 발생할 수 있습니다. 따라서 매크로를 더 많은 괄호와 함께 작성하는 것이 좋습니다. | 함수 매개변수는 함수가 호출될 때 한 번만 평가되고 그 결과 값이 함수에 전달되므로 표현식의 평가 결과를 더 예측하기 쉽습니다. |
부작용이 있는 매개변수 | 매개변수는 매크로의 여러 위치로 대체될 수 있습니다. 매크로의 매개변수가 여러 번 평가되면 부작용이 있는 매개변수 평가로 인해 예측할 수 없는 결과가 발생할 수 있습니다. | 함수 매개변수는 매개변수를 전달할 때 한 번만 호출되므로 결과를 예측하기가 더 쉽습니다. |
매개변수 유형 | 매크로의 매개변수는 유형과 관련이 없으며 매개변수에 대한 조작이 합법적인 한 모든 매개변수 유형과 함께 사용할 수 있습니다. | 함수의 매개변수는 유형과 관련되어 있습니다. 매개변수의 유형이 다르면 동일한 작업을 수행하더라도 다른 함수가 필요합니다. |
디버그 | 매크로는 디버깅이 불편합니다 | 기능을 단계별로 디버깅할 수 있습니다. |
재귀 | 매크로는 재귀적일 수 없습니다. | 함수는 재귀적일 수 있습니다. |
장점을 결합할 수 있는 방법이 있나요?
C++에서 도입됨인라인 함수 인라인 인라인~에엘~에이자형 ——매크로와 함수의 장점을 모두 가지고 있습니다.
매크로만큼 빠르게 실행되지만 함수와 동일한 효과를 갖습니다.