Si je l'ai fait :
#define MAXLINE 5000
Quel est le type de MAXLINE ? Dois-je supposer qu'il s'agit d'un int
? Puis-je le tester d'une manière ou d'une autre ?
En général, comment peut-on déterminer le type de #define
ed variable ?
Si je l'ai fait :
#define MAXLINE 5000
Quel est le type de MAXLINE ? Dois-je supposer qu'il s'agit d'un int
? Puis-je le tester d'une manière ou d'une autre ?
En général, comment peut-on déterminer le type de #define
ed variable ?
Il n'a pas de type. Il s'agit d'une simple substitution de texte. Le texte 5000 sera déposé à la place partout où MAXLINE apparaît comme un token.
Par exemple :
int a = MAXLINE;
mettra la valeur 5000 dans a
.
Alors que
char *MAXLINE2 = "MAXLINE";
n'entraînera pas
char *50002 = "5000";
Donc, si vous voulez un contrôle de type, les macros ne sont pas la solution. Vous voudrez déclarer des constantes statiques à la place, de cette façon la vérification du type est effectuée par le compilateur.
Pour plus d'informations sur les différences entre static
, const
y #define
il existe de nombreuses sources, dont cette question : Static, define, et const en C
(Très !) En gros, votre compilateur C va effectuer 3 tâches lors de son exécution :
Exécutez une passe de prétraitement sur vos fichiers sources,
Exécuter un compilateur sur les fichiers sources prétraités.
Exécutez un éditeur de liens sur les fichiers objets résultants.
Les lignes commençant par un #
J'aime la ligne
#define MAXLINE 5000
est géré par la phase de préprocesseur. (de manière simpliste) Le préprocesseur va analyser un fichier et effectuer des substitutions de texte pour toutes les macros qu'il détecte. Il n'y a pas de concept de type dans le préprocesseur.
Supposons que vous ayez les lignes suivantes dans votre fichier source :
#define MAXLINE 5000
int someVariable = MAXLINE; // line 2
char someString[] = "MAXLINE"; // line 3
Le préprocesseur détectera la macro MAXLINE
à la ligne 2, et effectuera une substitution de texte. Notez qu'à la ligne 3 "MAXLINE"
n'est pas traitée comme une macro, car il s'agit d'une chaîne littérale.
Une fois la phase de préprocesseur terminée, la phase de compilation ne verra que ce qui suit :
int someVariable = 5000; // line 2
char someString[] = "MAXLINE"; // line 3
(les commentaires ont été laissés pour plus de clarté, mais sont normalement supprimés par le préprocesseur) Vous pouvez probablement utiliser une option sur le compilateur pour pouvoir inspecter la sortie du préprocesseur. Dans gcc, l'option -E
permet de le faire.
Notez que bien que le préprocesseur n'ait pas de concept de type, il n'y a aucune raison pour que vous ne puissiez pas inclure un type dans votre macro par souci d'exhaustivité, par exemple
#define MAXLINE ((int)5000)
Il n'a pas de type. C'est juste un jeton que le préprocesseur va placer dans le code source avant de transmettre le code au compilateur. Vous pouvez faire cette chose (ridicule) de déclarer une variable appelée x5000
:
#define APPEND(x,y) x ## y
int main() {
int APPEND(x,5000);
x5000 = 3;
}
Le préprocesseur le transforme en ceci avant de le passer au compilateur proprement dit :
int main() {
int x5000;
x5000 = 3;
}
Donc, juste parce que tu vois 5000
dans une macro, cela ne signifie pas qu'elle doive être numérique de quelque manière que ce soit.
MAXLINE
n'est pas du tout une variable. En fait, ce n'est pas de la syntaxe C. Une partie du processus de compilation fait tourner un préprocesseur avant le compilateur, et l'une des actions du préprocesseur est de remplacer les instances de MAXLINE
dans le fichier source avec tout ce qui suit #define MAXLINE
(5000 dans le code de la question).
Par ailleurs, une autre façon courante d'utiliser le préprocesseur dans votre code est avec la fonction #include
que le préprocesseur remplace simplement par le contenu prétraité du fichier inclus.
Prenons un exemple du processus de compilation en action. Voici un fichier, foo.c
qui seront utilisés dans les exemples :
#define VALUE 4
int main()
{
const int x = VALUE;
return 0;
}
J'utilise gcc
y cpp
( le préprocesseur C ) pour les exemples, mais vous pouvez probablement le faire avec n'importe quelle suite de compilateurs que vous avez, avec des drapeaux différents, bien sûr.
Tout d'abord, nous allons compiler foo.c
con gcc -o foo.c
. Que s'est-il passé ? Cela a fonctionné ; vous devriez maintenant avoir un exécutable foo
.
Vous pouvez dire gcc
pour ne faire que le prétraitement et ne pas faire de compilation. Si vous faites gcc -E foo.c
vous obtiendrez le fichier prétraité sur la sortie standard. Voici ce qu'il produit :
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"
int main()
{
const int x = 4;
return 0;
}
Remarquez que la première ligne de main
a remplacé VALUE
con 4
.
Vous vous demandez peut-être à quoi correspondent les quatre premières lignes. Il s'agit de marqueurs de ligne, et vous pouvez en savoir plus à ce sujet dans la rubrique Sortie du préprocesseur .
Pour autant que je sache, il n'est pas possible d'ignorer purement et simplement le prétraitement en gcc
mais il existe quelques approches pour lui indiquer qu'un fichier a déjà été prétraité. Cependant, même si vous faites cela, il supprimera les macros présentes dans le fichier car elles ne sont pas destinées à être utilisées par le compilateur. Vous pouvez voir avec quoi le compilateur travaille dans cette situation avec gcc -E -fpreprocessed foo.c
:
.
.
.
.
int main()
{
const int x = VALUE;
return 0;
}
Remarque : j'ai mis les points en haut ; faites comme si c'étaient des lignes vides (j'ai dû les mettre là pour que ces lignes soient affichées par SO).
Ce fichier ne sera pas compilé (essayez gcc -fpreprocessed foo.c
pour le savoir) parce que VALUE
est présent dans la source, mais n'est défini nulle part.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.