Section courante

A propos

Section administrative du site

 Langage  Installation  Elément  Tutoriel  Programmation  Bibliothèque  API  Cadre d'application  Plateforme  Normes  IDE  Annexe  Aide 
ABAP/4
Ada
Assembleur
Assembly & bytecode
ASP (Active Server Pages)
Basic
C
C++
C# (C Sharp)
Cobol
ColdFusion
Fortran
HTML
Java
JavaScript
LISP
Logo
LotusScript
Oberon
Pascal
Perl
PHP
PL/1
Prolog
Python
Rebol
REXX
Ruby
SAS
NoSQL
SQL
Swift
X++ (Axapta)
GNAT
SMALLAda
VHDL
Assembleur 370
Assembleur 1802
Assembleur 4004
Assembleur 6502
Assembleur 6800
Assembleur 68000
Assembleur 8080 et 8085
Assembleur 8089
Assembleur 80x86
Assembleur AGC4
Assembleur ARM
Assembleur DPS 8000
Assembleur i860
Assembleur Itanium
Assembleur MIPS
Assembleur PDP-11
Assembleur PowerPC
Assembleur RISC-V
Assembleur SPARC
Assembleur SuperH
Assembleur UNIVAC I
Assembleur VAX
Assembleur Z80
Assembleur Z8000
Assembleur z/Architecture
ASSEMBLER/MONITOR 64
Micol Assembler
GFA Assembler
A86
MASM (Macro Assembler)
TASM (Turbo Assembler)
CIL
Jasmin
LLVM
MSIL
Parrot
P-Code (PCode)
SWEET16
G-Pascal
ASP 1.0
ASP 2.0
ASP 3.0
ASP.NET
ASP.NET Core
ABasiC (Amiga)
Adam SmartBASIC
Altair BASIC
AmigaBASIC (Amiga)
AMOS Basic (Amiga)
Atari Basic (Atari 400, 600 XL, 800, 800XL)
Basic Apple II (Integer BASIC/APPLESOFT)
Basic Commodore 64 (CBM-BASIC)
Basic Commodore 128 (BASIC 7.0)
Basic Commodore VIC-20 (CBM-BASIC 2.0)
Basic Coco 1 (Color Basic)
Basic Coco 2 (Extended Color Basic)
Basic Coco 3 (Extended Color Basic 2.0)
BASICA (PC DOS)
Basic Pro
BBC BASIC
Blitz BASIC (Amiga)
DarkBASIC
Dartmouth BASIC
GFA-Basic (Atari ST/Amiga)
GWBASIC (MS-DOS)
Liberty BASIC
Locomotive BASIC (Amstrad CPC)
MSX-Basic
Omikron Basic (Atari ST)
Oric Extended Basic
Power Basic
Quick Basic/QBasic (MS-DOS)
Sinclair BASIC (ZX80, ZX81, ZX Spectrum)
ST BASIC (Atari ST)
Turbo Basic
Vintage BASIC
VBScript
Visual Basic (VB)
Visual Basic .NET (VB .NET)
Visual Basic pour DOS
Yabasic
BeckerBASIC
SIMONS' BASIC
Basic09 d'OS-9
Disk Extended Color Basic
Basic09 d'OS-9
Disk Extended Color Basic
Access
Excel
Visual Basic pour Windows
Visual Basic .NET pour Windows
C Shell Unix (csh)
C pour Amiga
C pour Atari ST
C pour DOS
C pour Falcon030
C pour GEMDOS (Atari ST)
C pour Linux
C pour PowerTV OS
C pour OS/2
C pour Unix
C pour Windows
Aztec C
CoCo-C
GNU C
HiSoft C
IBM C/2
Introl-C
Lattice C
Microsoft C
MinGW C
MSX-C
Open Watcom C
OS-9 C Compiler
Pure C
Quick C
Turbo C
HiSoft C for Atari ST
HiSoft C for CP/M (Amstrad CPC)
C++ pour OS/2
C++ pour Windows
Borland C++
C++Builder
IBM VisualAge C++
Intel C++
MinGW C++
Open Watcom C++
Symantec C++
Turbo C++
Visual C++
Visual C++ .NET
Watcom C++
Zortech C++
C# (C Sharp) pour Windows
Apple III Cobol
Microsoft Cobol
BlueDragon
Lucee
OpenBD
Railo
Smith Project
Microsoft Fortran
WATFOR-77
CSS
FBML
Open Graph
SVG
XML
XSL/XSLT
LESS
SASS
GCJ (GNU)
JSP
Jython
Visual J++
Node.js
TypeScript
AutoLISP
ACSLogo
LotusScript pour Windows
Amiga Oberon
Oberon .NET
Apple Pascal
Delphi/Kylix/Lazarus
Free Pascal
GNU Pascal
HighSpeed Pascal
IBM Personal Computer Pascal
Lisa Pascal
Maxon Pascal
MPW Pascal
OS-9 Pascal
OSS Personal Pascal
Pascal-86
Pascal du Cray Research
Pascal/VS
Pascal-XT
PURE Pascal
QuickPascal
RemObjets Chrome
Sun Pascal
THINK Pascal
Tiny Pascal (TRS-80)
Turbo Pascal
UCSD Pascal
VAX Pascal
Virtual Pascal
Turbo Pascal for CP/M-80
Turbo Pascal for DOS
Turbo Pascal for Macintosh
Turbo Pascal for Windows
CodeIgniter (Cadre d'application)
Drupal (Projet)
Joomla! (Projet)
Phalanger (PHP .NET)
phpBB (Projet)
Smarty (balise)
Twig (balise)
Symfony (Cadre d'application)
WordPress (Projet)
Zend (Cadre d'application)
PL360
PL/M-80
PL/M-86
Turbo Prolog
CPython
IronPython
Jython
PyPy
AREXX
Regina REXX
JMP
Btrieve
Cassandra
Clipper
CouchDB
dBASE
Hbase
Hypertable
MongoDB
Redis
Access
BigQuery
DB2
H2
Interbase
MySQL
Oracle
PostgreSQL
SAP HANA
SQL Server
Sybase
U-SQL
Borland C++ 2.0
Borland C++ 3.0
Borland C++ 4.0
Microsoft C 5.0
Microsoft C 6.0
Microsoft C 7.0
QuickC 2.51
Turbo C 2.0
Turbo C++ 1.0
Turbo C++ 3.0
Visual C++ 1.0
Introduction
Les remarques
Généralité, grammaire et sémantique
Les opérateurs
Les instructions conditionnelles
Les instructions de boucles
Type de données
Fichier d'entête
Référence des mots réservés
Référence des fonctions
assert.h
ctype.h
math.h
setjmp.h
signal.h
stdarg.h
stdio.h
stdlib.h
string.h
time.h
Prototypes
Les premiers pas
Types, opérateurs et expressions
Contrôle du flux
Fonctions et structure du programme
Pointeurs et tableaux
Allocation de mémoire
Les structures
Entrée et sortie
Préprocesseur C
L'interface système UNIX
Bonjour
Astronomie
Biochimie
Conversion
Finance
Géographie
Géométrie
Histoire
Mathématique
Météorologie
Océanographie
Sport
Temps
Tri
Trigonométrie
Validation
Phase lunaire
Calcul du calcium corrigé
Calcul le taux d'alcoolémie
Bin,Hex,Base62,...
IPaymt/Interet
NPer
PPaymt/Principal
Distance en Km entre deux longitudes et latitudes
Aire d'un cercle
Aire d'une surface de prisme rectangulaire
Aire d'un triangle
Distance entre deux points
Chiffre romain
Ackermann
Exp
Factoriel
Fibonacci
Log
Nombre premier
Odd
Random
Round (arrondir)
Sqrt
Triangle Pascal
Valeur absolue (ABS)
Unité de mesure
Fréquence des vagues
Hockey
Année bissextile
Date de la Pâque
Heure courante
FirstDayOfMonth
Tri à bulle (Bubble Sort)
Tri Shell Sort
ArcCos
ArcSin
Atn/ATan/ArcTan/ArcTangente
Cos
Sin
Courriel
BoringSSL
CryptoAuthLib
GIFLIB
GnuTLS
libcurl
LibGD
libiconv
LibreSSL
libxml2
libzip
OpenGL
OpenSSL
QuicTLS
regex
zlib
API de Windows
API d'OS/2
Power TV OS API
BMC Atrium Core
NSAPI (Netscape Server Application Programmer's Interface)
OCI API pour Oracle Database SQL
Clearsilver
C pour Amiga
C pour Atari ST
C pour DOS
C pour GEMDOS
C pour Linux
C pour OS/2
C pour PowerTV OS
C pour UNIX
C pour Windows
ANSI C
C89
C90
C95
C POSIX
CodeBlocks
Eclipse
NetBeans
SET's Editor
Visual Studio
Xcode
Bibliographie
Préface
Notes légales
Dictionnaire
Recherche

Préprocesseur C

Conceptuellement, le préprocesseur est une phase de conversion étant appliquée à votre code source C avant que le compilateur lui-même ne le compile. A l'origine, le préprocesseur était un programme séparé, tout comme le compilateur et l'éditeur de liens peuvent encore être des programmes séparés aujourd'hui. Généralement, le préprocesseur effectue des substitutions textuelles sur votre code source, de trois sortes de manières :

La syntaxe du préprocesseur est différente de la syntaxe du reste de C à plusieurs égards. Tout d'abord, le préprocesseur est basé sur la ligne. Chacune des directives de préprocesseur commencent toutes par le caractère «#» doit être au début d'une ligne et chacune se termine à la fin de la ligne. Le reste de C traite les fins de ligne comme un simple espace supplémentaire et ne se soucie pas de la façon dont le texte de votre programme est organisé en lignes. Deuxièmement, le préprocesseur ne connaît pas la structure de C - à propos des fonctions, instructions ou expressions. Il est possible de jouer d'étranges tours avec le préprocesseur pour transformer quelque chose ne ressemblant pas à C en C (ou vice versa). Il est également possible de rencontrer des problèmes lorsqu'une substitution de préprocesseur ne fait pas ce que vous attendiez, car le préprocesseur ne respecte pas la structure des instructions et expressions C (mais vous vous y attendiez). Pour les utilisations simples du préprocesseur dont nous allons parler, vous ne devriez avoir aucun de ces problèmes, mais vous devrez faire attention avant de faire quoi que ce soit de délicat ou de scandaleux avec le préprocesseur.

Inclusion de fichiers

Une ligne du format :

#include <nomfichier.h>

ou

#include "nomfichier.h"

provoque la lecture, l'analyse et la compilation du contenu du fichier nomfichier.h à ce stade. Après le traitement de nomfichier.h, la compilation se poursuit sur la ligne suivant le #include. Par exemple, supposons que vous soyez fatigué de retaper des prototypes de fonctions externes tels que :

  1. extern int mafonction(char [], int); 

en haut de chaque fichier source. Vous pouvez à la place placer le prototype dans un fichier d'entête, peut-être mafonction.h, puis simplement placer :

  1. #include "mafonction.h"

en haut de chaque fichier source où vous avez appelé mafonction. (Vous ne trouverez peut-être pas utile de créer un fichier d'entête complet pour une seule fonction, mais si vous aviez un paquet de plusieurs fonctions associées, il pourrait être très utile de placer toutes leurs déclarations dans un seul fichier d'entête.) mentionné, c'est exactement ce que sont les fichiers d'entête Standard tels que stdio.h - des collections de déclarations (y compris des déclarations de prototypes de fonctions externes) ayant à voir avec divers ensembles de fonctions de bibliothèque Standard. Lorsque vous utilisez #include pour lire un fichier d'entête, vous obtenez automatiquement les prototypes et autres déclarations qu'il contient, et vous devez utiliser des fichiers d'entête, précisément pour obtenir les prototypes et autres déclarations qu'ils contiennent. La différence entre les formats < > et " " est l'endroit où le préprocesseur recherche nomfichier.h. En règle générale, il recherche les fichiers inclus dans <> dans les répertoires centraux standard, et il recherche les fichiers inclus dans " " dans le répertoire courant ou dans le répertoire contenant le fichier source effectuant l'inclusion. Par conséquent, "" est généralement utilisé pour les fichiers d'entête que vous avez écrits, et <> est généralement utilisé pour les entêtes vous ayant fournis (que quelqu'un d'autre a écrits). L'extension «.h», au fait, signifie simplement entête, et reflète le fait que les directives #include se trouvent généralement en haut (tête) de vos fichiers source et contiennent des déclarations et définitions globales que vous mettriez autrement Là. Cette extension n'est pas obligatoire (vous pouvez théoriquement nommer vos propres fichiers d'entête comme vous le souhaitez) mais .h est traditionnel et recommandé. La raison pour laquelle il faut mettre quelque chose dans un fichier d'entête, puis utiliser #include pour extraire ce fichier d'entête dans plusieurs fichiers sources différents, c'est quand le quelque chose (quel qu'il soit) doit être déclaré ou défini de manière cohérente dans tous les fichiers source. Si, au lieu d'utiliser un fichier d'entête, vous avez tapé quelque chose dans chacun des fichiers source directement, et que quelque chose a jamais changé, vous devrez éditer tous ces fichiers source, et si vous en manquiez un, votre programme pourrait échouer des manières subtiles (ou sérieuses) en raison des déclarations non concordantes (c'est-à-dire en raison de l'incompatibilité entre la nouvelle déclaration dans un fichier source et l'ancienne dans un fichier source que vous avez oublié de modifier). Placer des déclarations et des définitions communes dans des fichiers d'entête signifie que si jamais elles changent, elles ne doivent être modifiées qu'à un seul endroit, ce qui est un système beaucoup plus fonctionnel.

Étant donné que les fichiers d'entête ne contiennent généralement que des déclarations externes et ne doivent pas contenir de corps de fonction, vous devez comprendre ce qui se passe et ce qui ne se passe pas lorsque vous ajouter un #include un fichier d'entête. Le fichier d'entête peut fournir les déclarations pour certaines fonctions, afin que le compilateur puisse générer du code correct lorsque vous les appelez (et pour qu'il puisse s'assurer que vous les appelez correctement), mais le fichier d'entête ne donne pas au compilateur le fonctionne eux-mêmes. Les fonctions réelles seront combinées dans votre programme à la fin de la compilation, par la partie du compilateur appelée l'éditeur de liens. L'éditeur de liens devra peut-être extraire les fonctions des bibliothèques, ou vous devrez peut-être indiquer au compilateur/éditeur de liens où les trouver. En particulier, si vous essayez d'utiliser une bibliothèque tierce contenant des fonctions utiles, la bibliothèque sera souvent livrée avec un fichier d'entête décrivant ces fonctions. L'utilisation de la bibliothèque est donc un processus en deux étapes : vous devez inclure le #include de l'entête dans les fichiers où vous appelez les fonctions de la bibliothèque, et vous devez dire à l'éditeur de liens de lire les fonctions de la bibliothèque elle-même.

Définition et substitution de macros

Une ligne de préprocesseur dans la format de syntaxe :

#define nom texte

définit une macro avec le nom spécifié, ayant comme valeur le texte de remplacement spécifié. Après cela (pour le reste du fichier source actuel), partout où le préprocesseur voit ce nom, il le remplacera par le texte de remplacement. Le nom suit les mêmes règles que les identificateurs ordinaires (il ne peut contenir que des lettres, des chiffres et des traits de soulignement et ne peut pas commencer par un chiffre). Puisque les macros se comportent tout à fait différemment des variables (ou fonctions) normales, il est courant de leur donner des noms étant tous des majuscules (ou du moins commençant par une majuscule). Le texte de remplacement peut être absolument n'importe quoi - il n'est pas limité à des nombres, à de simples chaînes de caractères ou à quoi que ce soit. L'utilisation la plus courante des macros est de propager diverses constantes et de les rendre plus auto-documentées. Prenons pour exemple :

  1. char ligne[100];
  2. /* ... */
  3. demandeligne(ligne,100);

Le code n'est ni lisible ni fiable; ce n'est pas nécessairement évident de savoir ce que sont tous ces 100 dispersés dans le programme, et si jamais nous décidons que 100 est trop petit pour que la taille du tableau contienne des lignes, nous devrons nous rappeler de changer le nombre en deux (ou plus) des endroits. Une bien meilleure solution consiste à utiliser une macro comme ceci :

  1. #define MAXLIGNE 100
  2. char ligne[MAXLIGNE];
  3. /* ... */
  4. demandeligne(ligne, MAXLIGNE);

Maintenant, si jamais nous voulons changer la taille, nous n'avons qu'à le faire à un seul endroit, et ce que signifient les mots MAXLIGNE saupoudrés dans le programme est plus évident que les nombres magiques 100. Puisque le texte de remplacement d'une macro de préprocesseur peut être n'importe quoi, il peut aussi être une expression, même si vous devez vous rendre compte que, comme toujours, le texte est remplacé (et peut-être évalué) plus tard. Aucune évaluation n'est effectuée lorsque la macro est définie. Par exemple, supposons que vous écrivez quelque chose comme&mbsp;:

  1. #define A 2
  2. #define B 3
  3. #define C A + B

C'est un exemple assez banal, mais la situation se présente dans la pratique. Puis, plus tard, supposons que vous écrivez :

  1. int y = C * 2; 

Si A, B et C étaient des variables ordinaires, vous vous attendez à ce que y aboutisse à la valeur 10. Mais voyons ce qui se passe. Le préprocesseur substitue toujours le texte aux macros exactement comme vous l'avez écrit. Donc, il remplace d'abord le texte de remplacement pour la macro C, entraînant :

  1. int y = A + B * 2; 

Ensuite, il remplace les macros A et B, entraînant :

  1. int y = 2 + 3 * 2; 

Ce n'est que lorsque le préprocesseur a terminé de faire tout ce remplacement que le compilateur entre en action. Mais quand il évalue cette expression (en utilisant la priorité normale de la multiplication sur l'addition), il finit par initialiser y avec la valeur 8 ! Pour se prémunir contre ce type de problème, il est toujours judicieux d'inclure des parenthèses explicites dans les définitions des macros contenant des expressions. Si nous devions définir la macro C comme :

  1. #define C (A + B)

alors la déclaration de y s'étendrait finalement à :

  1. int y = (2 + 3) * 2; 

et y serait initialisé à 10, comme nous nous y attendions probablement. Notez qu'il n'est pas nécessaire (et en fait il n'y en a généralement pas) de point-virgule à la fin d'une ligne #define. (Ce n'est qu'une des raisons pour lesquelles la syntaxe du préprocesseur est différente du reste de C.) Si vous tapez accidentellement :

#define MAXLIGNE 100;

puis quand vous déclarez plus tard :

  1. char ligne[MAXLIGNE]; 

le préprocesseur l'étendra de la façon suivante :

char ligne[100;];

étant une erreur de syntaxe. C'est ce que nous voulons dire quand nous disons que le préprocesseur ne sait pas grand-chose sur la syntaxe de C, dans ce dernier exemple, la valeur ou le texte de remplacement de la macro MAXLIGNE était les 4 caractères «100;», et c'est exactement ce que le préprocesseur a remplacé (même si cela n'avait aucun sens). Les macros simples comme MAXLIGNE agissent un peu comme de petites variables, dont les valeurs sont constantes (ou expressions constantes). Il est également possible d'avoir des macros ressemblant à de petites fonctions (c'est-à-dire que vous les appelez avec ce qui ressemble à une syntaxe d'appel de fonction, et elles se développent en texte de remplacement étant une fonction des paramètres réels avec lesquels elles sont appelées) mais nous ne le ferons pas regardez-les encore.

Compilation conditionnelle

La dernière directive de préprocesseur que nous allons examiner est #ifdef. Si vous avez la séquence :

#ifdef nom
textedeprogramme
#else
autretextedeprogramme
#endif

dans votre programme, le code étant compilé dépend du fait qu'une macro de préprocesseur portant ce nom est définie ou non. Si tel est le cas (c'est-à-dire s'il y a eu une ligne #define pour une macro appelée nom), alors «textedeprogramme» est compilé et «autretextedeprogramme» est ignoré. Si la macro n'est pas définie, «autretextedeprogramme» est compilé et «textedeprogramme» est ignoré. Cela ressemble beaucoup à une instruction if, mais elle se comporte complètement différemment : une instruction if contrôle quelles instructions de votre programme sont exécutées au moment de l'exécution, mais #ifdef contrôle quelles parties de votre programme sont réellement compilées. Tout comme pour l'instruction if, le #else dans un #ifdef est facultatif. Il existe une directive compagnon #ifndef, compilant le code si la macro n'est pas définie (bien que la clause «#else» d'une directive #ifndef sera alors compilée si la macro est définie). Il existe également une directive #if compilant le code selon qu'une expression à la compilation est vraie ou fausse. Les expressions autorisées dans une directive #if sont cependant quelque peu restreintes.



PARTAGER CETTE PAGE SUR
Dernière mise à jour : Dimanche, le 8 novembre 2020