2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Il y a quelques paramètres en langage CSymboles prédéfinis, peut être utilisé directement, les symboles prédéfinis sont在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
Exemple:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
résultat de l'opération :
Je voudrais mentionner ici que VS ne prend pas entièrement en charge ANSI C (standard C); gccgccgcc Prend en charge ANSI C (norme C)
Syntaxe de base :
# define name stuff
Par exemple:
#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__ )
- La deuxième phrase est la paresse, pourquoi ?
- La troisième phrase pour pourFou Circulaire
初始化、判断、调整都可以省略
, mais si le jugement est omis, cela signifie que la condition du jugement est toujours vraie, c'est-à-direboucle infinie- Il est préférable de ne pas faire cela lors du quatrième match, cela peut facilement causer des problèmes.
- La cinquième phrasecaractère de continuation de ligneIl s'agit d'éviter les problèmes après le branchement.
转义
Dos回车符
, afin que le retour chariot ne soit plus un retour chariot.Il ne peut y avoir rien après le caractère de continuation de ligne, appuyez sur“”
Appuyez simplement sur Entrée, sinon la suite ne sera pas la ligne de code suivante.
Maintenant vient le problème : utilisez # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt Lors de la définition d’un identifiant, faut-il l’ajouter à la fin ?;
?
Par exemple:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
Le code ci-dessus plus;
, cela semble juste un peu redondant, mais cela n'a aucun impact sur le fonctionnement du programme.
Il semble ajouter;
Ou n'ajoute pas;
Ça va aller?
est-ce vraiment comme ça ?
Regardons l'exemple suivant :
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
Après remplacement :
printf("%dn", 1000;);
Imprimer1000;
Que signifie ?
if (1)
max = 1000;
;
else
max = 1;
autre autreetttttttttttttttttttttttttttttttttlse À qui correspondre ?
Vous voyez, il y a quelque chose qui ne va pas avec ça, alorsutiliser # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt Lors de la définition d'un indicateur, ne l'ajoutez pas après;
# définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt Le mécanisme comprend une disposition,允许把参数替换到文本中
, cette implémentation est souvent appeléeMacro (marco) (marco)(maisisisrco)ou Définir une macro ( definemacro ) (define macro)(detttttttttttttttttttttttttttttttttFdansetttttttttttttttttttttttttttttttttmaisisiscro)
La différence entre les macros et les identifiants de définition de macro ci-dessus est :La macro a des paramètres
Voici comment la macro est déclarée :
#define name(parament - list) stuff
l'un d'eux paragraphe paragraphepunlsuisetttttttttttttttttttttttttttttttttnt - liste listeljemt(liste de paramètres) est une liste de symboles séparés par des virgules qui peuvent apparaître dans des trucs des trucsmttoiff milieu
Note: paragraphe paragraphepunlsuisetttttttttttttttttttttttttttttttttnt - liste listeljemt(liste des paramètres)Parenthèse gaucheDoit être avec nom nomnomettttttttttttttttttttttttttttttttt près de, s'il existe un espace entre eux, la liste d'arguments est interprétée comme des trucs des trucsmttoiff une partie de.
Exemple:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
résultat de l'opération :
Comme vous pouvez le constater, le carré de 5 est correctement calculé
Mais en fait, il y a un problème avec le code ci-dessus. Veuillez consulter l'extrait de code suivant :
int a = 5;
printf("%dn", SQUARE(a + 1));
résultat de l'opération :
Pourquoi cela est-il ainsi? Le résultat de 5+1 est 36, et 6 ∗ * ∗ 6 devrait être 36. Comment avez-vous obtenu 11 ?
Le problème vient des macros, nous le savons宏是直接替换
, alors le résultat du remplacement direct du code ci-dessus est :
printf("%dn", a+1*a+1);
5 + 6 + 1, le résultat est naturellement 11
Nous pouvons facilement résoudre ce problème en ajoutant des parenthèses des deux côtés de la définition de la macro.
#define SQUARE(x) (x)*(x)
Il n'y a donc aucun problème avec cette définition ?Jetons un coup d'œil à la définition de macro suivante :
#define DOUBLE(X) (X)+(X)
Nous avons utilisé des parenthèses dans la définition pour éviter le problème précédent, mais cette macro peut provoquer de nouvelles erreurs.
int a = 5;
printf("%dn", 10 * DOUBLE(a));
résultat de l'opération :
Le résultat de sortie n’est pas 100 mais 55. La raison est similaire à celle ci-dessus. Question prioritaire
Solution:
#define DOUBLE(X) ((X)+(X))
En résumé, lors de l'utilisation de macrosNe lésinez jamais sur les parenthèsespour éviter les interactions inattendues entre les opérateurs dans les paramètres ou les opérateurs adjacents lors de l'utilisation de macros.
Lorsqu'un paramètre de macro apparaît plus d'une fois dans la définition de la macro, si le paramètre aeffet secondaire, alors vous pourriez être en danger en utilisant cette macro, ce qui entraînerait不可预测
Le résultat de. Les effets secondaires sont des effets permanents lorsque l’expression est évaluée.
Par exemple:
x + 1; //不带副作用
x++; //带副作用
La macro MAX suivante illustre les problèmes causés par les paramètres ayant des effets secondaires.
#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;
}
résultat de l'opération :
Pourquoi cela est-il ainsi?Analysons-le ensemble
z = ((X++) > (y++) ? (x++) : (y++))
- Portez d’abord un jugement : xxX++ avec ouaiset++ jugement, car c'est postfix ++, pour juger xxX est 5, ouaiset est 8, 8 > 5
- Après avoir jugé xxX est 6, ouaiset pour 9
- Puis exécutez ouaiset ++, car il est postfixé ++, le résultat est 9
- Puis continuez ouaiset Effectuer une incrémentation automatique, ouaiset Le résultat final est 10
nous allons xxX et ouaiset Une fois passés dans la macro, les résultats ont changé, notamment ouaiset, après deux changements, tu as dit que c'était pas terrible
Lorsqu'un paramètre avec des effets secondaires est transmis à une macro et que le paramètre apparaît plus d'une fois dans la macro, l'effet secondaire du paramètre est également plus d'une fois.
Développer dans le programme # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt La définition des symboles et des macros comporte plusieurs étapes.
参数进行检查
, voyez s'il contient # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt Défini标识符
.Si c'est le cas, ils sont remplacés en premier被插入
à l'emplacement d'origine dans le programme, avec les noms des paramètres de macro remplacés par leurs valeurs#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
MAX dans le code ci-dessus est également représenté par # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt DéfiniMacro .Lors du dernier contrôle, son paramètre M a été remplacé. Il est temps de le remplacer cette fois.
MAX ( x , 10 ) MAX(x, 10)MUNX(X,10) est remplacé par ( ( x ) > ( 10 ) ((x) > (10)((X)>(10)
?
?
? ( x ) : ( 10 ) ) (x):(10))(X):(10))
certainement,宏里面嵌套宏
c'est bien aussi
MAX(x, MAX(2, 3))
À ce stade, remplacez d'abord la macro dans le paramètre, puis remplacez la macro entière
Mais il faut noter que cela不是递归
, qui n'est qu'une macro qui sert d'argument à une autre macro.递归是宏内部又调用了宏本身
。
De plus, lorsque le préprocesseur recherche # définir définirdetttttttttttttttttttttttttttttttttFdansettttttttttttttttttttttttttttttttt Lors de la définition d'un symbole,Le contenu des constantes chaîne n'est pas recherché
Qu'est-ce que cela signifie?Donnez juste une châtaigne et vous comprendrez.
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
Dans le code ci-dessusprintf("M = %d", x);
milieu MMM ne sera pas remplacé par 10
La macro ci-dessus est utilisée pour trouver la plus grande valeur de deux nombres. Nous pouvons l’écrire complètement sous forme de fonction.
int Max(int x, int y)
{
return x > y ? x : y;
}
Nous avons constaté qu’ils remplissent tous la même fonction.Mais pour la fonction "trouver le plus grand de deux nombres", l'écriture de la macro sera更有优势
Quelques
Il y a deux raisons :
- utilisé pour
调用函数
et函数返回
decodepeut prendre plus de temps que l'exécution réelle de ce petit calcul (lors de l'appel de la fonctionCréer un cadre de pile ).Par conséquent, la fonction macro ratio est dans le programme规模
et速度
Mieux que jamais- Plus important
函数的参数必须声明类型
, ce qui entraîne l'utilisation de la fonction uniquement sur les expressions du type approprié.Au contraire, cette macro peut s'appliquer à de nombreux types : entier, entier long, virgule flottante, etc.
>
Comparer.Les paramètres de la macro sontType indépendantde。
Utiliserons-nous toujours des macros à l’avenir ?En fait, les macros ne sont utilisées que pourCalcul simple, ne convient pas aux opérations et fonctions complexes et volumineuses par rapport aux macros Désavantages:
- Chaque fois qu'une macro est utilisée, une copie du code de définition de la macro est insérée dans le programme.À moins que la macro soit relativement courte, elle peut
大幅度增加程序的长度
- la macro est
没法调试
de- Les macros sont indépendantes du type, c'est-à-dire
不够严谨
- Les macros peuvent provoquer des problèmes de priorité d'opération, provoquant l'arrêt du programme.
容易出错
Mais parfois, les macros peuvent faire des choses que les fonctions ne peuvent pas faire.
Par exemple:
int* p = (int*)malloc(10 * sizeof * (int));
Nous n'aimons pas l'écrire comme ça malloc mallocmaisisislloc La fonction est trop lourde, je veux大小
et类型
Passez-le pour ouvrir de l'espace
Malloc(10, int);
Les fonctions peuvent-elles faire cela ?Non parce queLes fonctions ne peuvent pas transmettre de types
Et les macros peuvent le faire, parce que les macros ne le font pas.Ne vérifie pasvos paramètrestaperde
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
Une comparaison des macros et des fonctions :
Les attributs | # définir définirdetttttttttttttttttttttttttttttttttFdansetttttttttttttttttttttttttttttttttDéfinir une macro | fonction |
---|---|---|
longueur du code | Chaque fois qu'il est utilisé, du code macro sera inséré dans le programme. À l'exception des très petites macros, la longueur du programme augmentera considérablement. | La valeur du code de fonction apparaît à un endroit et chaque fois que la fonction est utilisée, le même code à cet endroit est appelé. |
Vitesse d'exécution | plus rapide | Il y a la surcharge supplémentaire liée aux appels et aux retours de fonctions (ouverture des cadres de pile), alors commençons par les plus lents. |
priorité des opérateurs | Les paramètres de macro sont évalués dans le contexte de toutes les expressions environnantes. À moins que des parenthèses ne soient incluses, la priorité des opérateurs adjacents peut avoir des conséquences imprévisibles. Par conséquent, il est recommandé d'écrire des macros avec plus de parenthèses. | Les paramètres de fonction ne sont évalués qu'une seule fois lorsque la fonction est appelée, et sa valeur de résultat est transmise à la fonction, ce qui rend le résultat de l'évaluation de l'expression plus prévisible. |
Paramètres avec effets secondaires | Les paramètres peuvent être remplacés à plusieurs positions dans la macro. Si les paramètres de la macro sont évalués plusieurs fois, l'évaluation des paramètres avec des effets secondaires peut produire des résultats imprévisibles. | Les paramètres de fonction ne sont appelés qu'une seule fois lors du passage des paramètres, et les résultats sont plus faciles à prédire. |
Type de paramètre | Les paramètres de la macro n'ont rien à voir avec le type. Tant que l'opération sur les paramètres est légale, elle peut être utilisée avec n'importe quel type de paramètre. | Les paramètres d'une fonction sont liés au type. Si les paramètres sont de types différents, différentes fonctions sont requises, même si elles effectuent la même tâche. |
déboguer | Les macros ne sont pas pratiques à déboguer | Les fonctions peuvent être déboguées étape par étape |
récursivité | Les macros ne peuvent pas être récursives | Les fonctions peuvent être récursives |
Existe-t-il un moyen de combiner leurs avantages ?
Introduit en C++fonction en ligne en ligne en lignedansldansettttttttttttttttttttttttttttttttt ——A les avantages des macros et des fonctions
Il s'exécute aussi vite qu'une macro mais a le même effet qu'une fonction