Programme :
•Historique du langage
•Typologie des langages informatiques, comparaison avec Matlab, JAVA
•Mots-clés et opérateurs du C++ : les ajouts au C
•Types de base C et ajouts du C++
•Les « littéraux » en C et C++
•Le type bool en C++
•Les identifieurs (symboles) en C/C++
•Comparaison entre les notions de « définition » et de « déclaration »
•La définition des variables, leur portée, la résolution de leur portée
•Le préprocesseur C/C++, l’organisation modulaire des fichiers
•La définition et déclaration des tableaux, des constantes et des chaînes de caractères
•Les opérateurs logiques et mathématiques
•Les structures de contrôle (if, while, for, do, switch)
•Les énumérations
•La conversion des types en C, et en C++
•Fonctions et procédures en C et C++
•En C++ : fonction « en ligne », arguments par défaut et surcharge des noms de fonctions
•Les pointeurs, indirection, lien avec les tableaux, leur « arithmétique »
•Les types complexes (struct, union). Les alias de types
•Les références
•Le passage des arguments en C, en C++. Les valeurs de retour des fonctions
•Allocation dynamique de la mémoire et sa gestion
D’après « Langage C++, le standard ANSI/ISO expliqué, J. Charbonnel, Dunod, 1997 » :
En 1980, le langage C est le plus utilisé dans le monde. Il allie flexibilité, efficacité, disponibilité et portabilité.
Un étudiant de l’Université de Cambridge, Bjarne Stroustrup décide d’incorporer la notion de classes au C. Il s’agit d’abord d’un préprocesseur utilisé en amont du compilateur : C with classes. [1]
Le nouveau langage incorpore des influences positives venant de Simula, Pascal, Modula- 2, Ada, Smalltalk, Algol.
En 1983, Stroustrup décide d’implémenter une version à l’aide des technologies traditionnelles des compilateurs. Il s’appelle Cfront, il génère du C pour obtenir un maximum de portabilité, mais ce n’est pas un préprocesseur. [2]
Page 2
Notes :
[1] : un préprocesseur génère du code source (texte) à partir du code source (texte) de l’utilisateur. Le langage C/C++ dispose d’un préprocesseur très puissant (c’est lui qui comprend les directives #include, #define, #if, etc.).
[2] : le processus d’obtention des exécutables est alors :
code source C++ => préprocesseur C => Cfront => compilateur C => exécutable
La première version officielle du langage est publiée par les laboratoires Bell Labs d’AT&T en 1986, elle est numérotée 1.0. [1]
Elle est suivie des versions 1.1 et 1.2.
La version 2.0 sort en juin 1989, elle apporte l’héritage multiple, les classes abstraites, les méthodes statiques, les méthodes constantes.
La version 2.1 corrige certains bugs. La version 3.0 ajoute la notion de templates et la version 4.0 la gestion des exceptions. [2]
A partir de cette date, le nombre d’utilisateurs explose. Plusieurs sociétés proposent des compilateurs C++. L’implémentation libre G++ de GNU apparaît.
Page 3
Notes :
[1] : Bjarne Stroustrup, The C++ programming language, 1986 – Addison-Wesley.
[2] : M.A. Ellis et Bjarne Stroustrup, The annotated C++ Reference Manual, 1990 – Addison-Wesley
Dès 1988, il apparaît nécessaire de normaliser le langage.
Avec l’appui de HP, AT&T, DEC et IBM, Bjarne Stroustrup s’y attelle. La première réunion du comité de normalisation a lieu en décembre 1989 à Washington.
En 1998, le travail est terminé et approuvé :
« ISO/IEC International Standard 14882 – Programming language C++, 1998 »
En 2003, une nouvelle version de la norme :
Page 4
Recensement des utilisateurs dans le monde :
1979 : 1
1980 : 16
1981 : 38
1983 : 85
1985 : 500
1987 : 4 000
1989 : 50 000
1991 : 400 000
Par la suite, le décompte devient impossible (en 1992, Borland fait état de 500 000 compilateurs en service).
Figé Dynamique
Page 5
Explication :
La grande différence entre les langages compilés et les langages interprétés vient de la capacité ou non à étendre le code durant l’exécution du programme. Le principe d’ajouter du code durant l’exécution n’est pas difficile à comprendre : il suffit de penser à une fonction qui crée d’autres fonctions quand on l’exécute.
On peut aussi distinguer les langages selon leur façon de gérer le typage des variables :
Les types sont fixés à la compilation.
Déclaration de toutes les variables et de leur type avant leur utilisation.
Un langage dans lequel les types sont découverts à l’exécution.
Détermination du type d’une variable la première fois qu’on lui assigne une valeur.
Page 6
Précisions :
En règle générale : les langages interprétés sont à typage dynamique, alors que les langages compilés sont à typage statique.
Code Figé | Données Figées | Code Dynamique | Données Dynamiques | ||
Fortran - > F77 | X | X | |||
Lisp, Smalltalk | X | X | |||
Fortran F90 | X | X | X | ||
C / C++ | X | X | X | ||
Java | X |
| X | ||
Python, Matlab | X |
| X |
Page 7
Précisions :
-Fortran (jusqu’à F77) : pas d’allocation dynamique
-Lisp et Smalltalk sont des langages interprétés, tout est dynamique et du code peut générer du code
-Matlab et Python sont aussi interprétés, mais il n’est pas standard de rajouter du code durant l’exécution (définition de fonctions « lambda » en Python)
-Fortran 90, C et C++ sont des langages compilés où l’allocation dynamique est possible
-En Java, l’allocation dynamique est la règle générale, sauf pour les types de base
Au lancement du programme, l’espace mémoire est vide :
Page 8
Puis on peut ajouter des variables, elles sont allouées dynamiquement et l’espace de travail se remplit :
On peut détruire des variables avec la commande « clear ».
Page 9
On peut créer un fichier qui contient le code d’une nouvelle fonction et l’utiliser immédiatement :
Page 10
Un extrait de la documentation MATLAB :
What Happens When You Call a Function
When you call a function M-file from either the command line or from within another M-file, MATLAB parses the function into pseudocode and stores it in memory. This prevents MATLAB from having to reparse a function each time you call it during a session. The pseudocode remains in memory until you clear it using the clear function, or until you quit MATLAB.
On peut écrire une fonction qui fabrique cette nouvelle fonction, mais MATLAB n’est pas un pur langage interprété et on ne peut utiliser tout de suite la nouvelle fonction :
Précision :
Comme le montre la trace, il faut appeler deux fois la fonction « create_function ». Le premier appel retourne une erreur, mais crée le fichier « essai.m », ce qui permet au deuxième appel de fonctionner.
Dans le même ordre d’idées, il ne semble pas possible de créer une fonction en utilisant la console de commande (on obtient un message du genre « ??? Strings passed to EVAL cannot contain function declarations »).
Une chose importante à connaître est le mode utilisé par chaque langage pour passer les paramètres aux fonctions et procédures.
La fonction ne connaît pas la variable de départ, seulement sa valeur.
La variable ne peut être modifiée par la fonction/procédure.
Comment alors écrire une fonction qui modifie des variables ? [1]
Passage par référence
La variable peut être modifiée par la fonction/procédure.
Comment alors distinguer entre celles qui modifient la variable et les autres ? [2]
Page 12
Précisions :
Une « procédure » est une fonction qui ne retourne pas de valeur. Certains langages font cette distinction, mais pas le C/C++.
[1] réponse du C/C++ : en passant la valeur de l’adresse de la variable (c’est-à-dire ce que l’on appelle un pointeur).
[2] réponse du C/C++ : en utilisant le mot-clé const pour signifier que la référence ne sera pas modifiée par la fonction.
MATLAB utilise le passage par valeur :
Page 13
Un extrait de la documentation MATLAB :
How MATLAB Passes Function Arguments
From the programmer's perspective, MATLAB appears to pass all function arguments by value. Actually, however, MATLAB passes by value only those arguments that a function modifies. If a function does not alter an argument but simply uses it in a computation, MATLAB passes the argument by reference to optimize memory use.
Le C utilise aussi le passage par valeur :
#include <stdio.h>
void f(double y) { y = 2 * y;
} void g(double *y) {
*y = 2 * *y;
} void main()
{ double x = 5;
printf("Valeur de x = %g\n", x);
f(x);
printf("Valeur de x = %g\n", x);
g(&x);
printf("Valeur de x = %g\n", x);
}
Page 14
Explications :
- La première fonction « f » reçoit la valeur de la variable, elle copie cette valeur dans une variable qui est locale à la fonction « f ». C’est cette valeur locale qui est multipliée par 2. Cela ne sert à rien, car la portée de cette variable est locale, justement.
- La deuxième fonction « g », reçoit aussi une valeur, mais c’est une adresse. La fonction utilise l’opérateur « * » qui signifie « la variable se trouvant à cette adresse » pour travailler sur la variable et modifier efficacement la valeur.
Nous verrons que la passage par référence du C++ simplifie grandement les choses.
Exemple : Exple_01_passageC
En JAVA, ça dépend. Les types de base sont passés par valeurs :
public class passage
{ static void f(double y) {
y = 2 * y;
}
public static void main(String[] args) { double x = 5.0;
.println("Valeur de x " + x);
f(x);
.println("Valeur de x " + x); }
};
Mais tous les autres types sont passés en référence.
Page 15
Précisions :
Il existe en JAVA la notion de « classes d’enveloppe des types de base » ou wrappers.
Par exemple « Double » est la classe enveloppe du type primitif « double ». Quoiqu’il en soit, après 2h de recherche, je n’ai pas trouvé comment réaliser une fonction qui modifie la valeur d’une variable simple.
Si quelqu’un veut bien chercher …
Passage par valeur | Passage par référence | |
MATLAB | OUI | Le langage l’utilise “dans le dos” du programmeur |
Fortran, Lisp, Smalltalk, Python | NON | OUI |
C | OUI => on passe les adresses des variables pour les modifier | NON |
C++ | oui, par défaut | possible, au choix du programmeur |
Java | oui, types simples “dans le dos” du programmeur | oui, objets “dans le dos” du programmeur |
Page 16
Conclusion :
Le C++ permet à l’utilisateur de choisir entre le passage par valeur et le passage par référence. Choix que ne permet aucun autre langage de la liste.
Le langage C++ est un langage compilé :
? le code est figé et ne peut être étendu durant l’exécution
? en contre- partie, gain énorme en performances
Les données peuvent être statiques ou allouées dynamiquement selon les choix du programmeur :
? statiques : gain de performance
? allouées dynamiquement : gain de place mémoire
Le langage C++ permet au programmeur de choisir entre le passage par valeur ou le passage par référence.
Page 17
Précisions :
De tous les langages, le C++ offre le plus de possibilités au programmeur. A part les contraintes liées à tout langage compilé, il n’impose aucun choix préconçu.
// Une fonction
// aimable en C++#include <iostream>
void main()
{ std::cout << "Hello" << std::endl;
}
Commentaires C Commentaires C++ Page 18 Exercice : | : /* sur plusieurs lignes */ : // sur une ligne |
- créer deux projets Exple_02_mainC et Exple_03_mainCPP
- ces projets comprennent chacun un programme principal
- « main.c » pour le code C
- « » pour le code C++
Tout ce qui était possible en C, l'est aussi en C++ :
/* les commentaires a la mode C */
#include <iostream>
#include <cstdio> // les librairies C
int main()
{ std::cout << "Hello" << std::endl;
printf ("Hello bis\n"); // les instructions Creturn0;
}
En général, on considère que le programme principal « main » doit retourner « 0 » s’il s’est correctement exécuté.
Page 19
Exercice :
- poursuivre le code des exemples Exple_02_mainC et Exple_03_mainCPP en créant un nouveau projet : Exple_04_mainCPP2
Le langage C dispose de 33 mot-clés :
asm | auto | break | case |
char | const | continue | default |
do | double | else | enum |
extern | float | for | goto |
if | int | long | register |
return | short | signed | sizeof |
static | struct | switch | typedef |
union | unsigned | void | volatile |
while
Auxquels on ajoute :
• des opérateurs unaires : – ~ ! * & sizeof + ++ ––
• des opérateurs binaires : . -> * / % + – << >> < >
<= >= == != & | ^ && ||
• des « ponctuations » : [ ] ( ) { } , : = ; ... #
Page 20
Le C++ introduit 41 nouveaux mot-clés qui s’ajoutent aux 33 du langage C :
bool | catch class | const_cast | |
delete | dynamic_cast explicit | export | |
false | friend | inline | mutable |
namespace | new | operator | private |
protected | public | static_cast | reinterpret_cast |
template | this | throw | true |
try | typeid | typename | using |
virtual | wchar_t | and(&&) | and_eq(&=) |
bitand(&) | bitor(|) | compl(~) | not(!) |
not_eq(!=) | or(||) | or_eq(|=) | xor(^) |
xor_eq(^=)
char *friend = "Jeremie" ; // illegalvoid delete(void *ptr); // illegalint new; // illegal
Page 21
Sur l’exemple de la planche, voici les erreurs produites par VisualC++ 6.0 :
warning C4518: 'friend ' : storage-class or type specifier(s) unexpected here; ignored error C2059: syntax error : '=' warning C4091: '' : ignored on left of 'void' when no variable is declared error C2143: syntax error : missing ';' before 'delete' error C2143: syntax error : missing ';' before 'delete' warning C4091: '' : ignored on left of 'int' when no variable is declared error C2143: syntax error : missing ';' before 'new' error C2143: syntax error : missing ';' before 'new'
D’où l’intérêt d’un bon éditeur (avec au minimum coloration syntaxique) pour faire apparaître ces motsclés.
Les mots-clés du langage C : asm auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
Exemple : Exple_05_motscles
Opérateur:: | Scope resolution Résolution de portée | binaire | |
:: | Global Portée globale | unaire | |
[ ] | Array subscript Manipulation de tableaux | binaire | gauche à droite |
( ) | Function call Appel de fonction | variable | gauche à droite |
. | Member selection (object) Sélection de membre | binaire | gauche à droite |
–> | Member selection (pointer) Sélection de membre | binaire | gauche à droite |
++ | Postfix increment Incrément (suffixe) | unaire | non |
–– | Postfix decrement Décrément (suffixe) | unaire | non |
Page 22
Précisions :
• L’opérateur :: permet de lever les ambiguïtés entre des variables de même nom
• Le choix de l’opérateur de sélection dépend de l’entité à laquelle il s’applique
• Il existe des opérateurs d’incrémentation et de décrémentation préfixés
Opérateur new | Allocate object Allocation dynamique | variable | |
delete | Deallocate object Libération mémoire | unaire ou binaire | |
delete[ ] | Deallocate object Libération mémoire (tableaux) | unaire ou binaire | non |
++ | Prefix increment Incrément (préfixe) | unaire | non |
–– | Prefix decrement Décrément (préfixe) | unaire | non |
* | Dereference Valeur du pointeur | unaire | non |
& | Address-of Adresse de | unaire | non |
– | Arithmetic negation (unary) Négation unaire | unaire | non |
Page 23
Précisions :
• Les opérateurs new et delete ont une grande importance en C++
• Les opérateurs * et & sont inverses l’un de l’autre
• L’opérateur de négation unaire est différent de l’opérateur de négation binaire
Opérateur! | Logical NOT Négation logique | unaire | |
~ | Bitwise complement Complément à un | unaire | |
sizeof | Size of object or type Taille d’une variable ou d’un type | unaire | non |
typeid( ) | Type name Nom d’un type (chaîne de caractères) | unaire | non |
(type) | Type cast (conversion) Conversion de type (transtypage) | binaire | droite à gauche |
.* | Apply pointer to class member (objects) Sélection de membre et déréferencement | binaire | gauche à droite |
–>* | Dereference pointer to class member Sélection de membre et déréferencement | binaire | gauche à droite |
* | Multiplication Multiplication | binaire | gauche à droite |
Page 24
Précisions :
• L’opérateur sizeof retourne une valeur du type size_t
• L’opérateur typeid retourne une valeur du type const type_info&
• Ne pas confondre la multiplication * et l’opérateur d’indirection *
Opérateur / | Division Division | ||
% | Remainder (modulus) Modulo | binaire | gauche à droite |
+ | Addition Addition | binaire | gauche à droite |
– | Subtraction Soustraction | binaire | gauche à droite |
<< | Left shift Décalage à gauche | binaire | gauche à droite |
>> | Right shift Décalage à droite | binaire | gauche à droite |
< | Less than Inférieur à | binaire | gauche à droite |
> | Greater than Supérieur à | binaire | gauche à droite |
Page 25
Précisions :
• Les opérateurs < et > retournent un booléen (bool)
Opérateur <= | Less than or equal to Inférieur ou égal à | ||
>= | Greater than or equal to Supérieur ou égal à | binaire | gauche à droite |
== | Equality Egalité | binaire | gauche à droite |
!= | Inequality Inégalité | binaire | gauche à droite |
& | Bitwise AND ET binaire (bits) | binaire | gauche à droite |
^ | Bitwise exclusive OR OU exclusif binaire (bits) | binaire | gauche à droite |
| | Bitwise OR OU binaire (bits) | binaire | gauche à droite |
&& | Logical AND ET logique (bool) | binaire | gauche à droite |
Page 26
Précisions :
• Les opérateurs de comparaison retournent un booléen (bool)
• Ne pas confondre les opérateurs logiques et ceux qui travaillent sur des champs de bits
Opérateur || | Logical OR OU logique (bool) | ||
e1?e2:e3 | Conditional Condition if-else | ternaire | droite à gauche |
= | Assignment Affectation | binaire | droite à gauche |
*= | Multiplication assignment Multiplication et affectation | binaire | droite à gauche |
/= | Division assignment Division et affectation | binaire | droite à gauche |
%= | Modulus assignment Modulo et affectation | binaire | droite à gauche |
+= | Addition assignment Addition et affectation | binaire | droite à gauche |
–= | Subtraction assignment Soustraction et affectation | binaire | droite à gauche |
Page 27
Précisions :
• L’opérateur conditionnel ternaire permet d’écrire des expressions plus concises qu’avec if-else
Opérateur <<= | Left-shift assignment Décalage à gauche et affectation | droite à gauche | |
>>= | Right-shift assignment Décalage à droite et affectation | binaire | droite à gauche |
&= | Bitwise AND assignment ET binaire et affectation | binaire | droite à gauche |
|= | Bitwise inclusive OR assignment OU binaire et affectation | binaire | droite à gauche |
^= | Bitwise exclusive OR assignment OU exclusif binaire et affectation | binaire | droite à gauche |
, | Comma Virgule | binaire | gauche à droite |
Page 28
Précisions :
• L’opérateur virgule sert à évaluer deux ou plusieurs expressions, là où une seule est autorisée
• Il ne faut pas le confondre avec le signe de ponctuation virgule
Exercice : trouver les N erreurs de ce programme (Exple_06_Nerreurs) struct MaStruct
{
MaStruct *this; // pointeur sur moi-même
MaStruct *friend; // pointeur sur le suivant
};
typedef MaStruct* try; void using(MaStruct* s) // fonction récursive
{ using(s->this); using(s->friend);
} void inline(MaStruct* new) // Affichage
{
MaStruct *public = new; cout << "INLINE\n" << public;
}
Types de base : char, int, float, double
+ des modificateurs optionnels : long, short, unsigned, signed
char c, ch; c = 'a'; ch = '\n'; int i, j; i = 10; long int ii; long jj; ii = 12345; jj = 888888L; int m = 1000; | short int mm; short nn; short pp = 100; unsigned int i1; unsigned long j1; unsigned short k1; i1 = 345U; j1 = 888888UL; signed int i2; signed long j2; signed short k2; | float x1, x2; float x3 = 0.1F; double y; long double z; x1 = 0.45; x2 =-3.5e12F; y = 0.45; z = 0.99e-2L; |
long n = 999999L;
void : pour spécifier qu’il n’y a pas de type
Page 29
Important :
En C, on met toutes les déclarations de variables au début des fonctions. On ne peut mélanger déclarations et affectations dans n’importe quel ordre comme dans l’exemple ci-dessus. En C++, c’est possible, les variables peuvent être déclarées n’importe où dans le code.
Précisions :
Par défaut, une constante :
- entière : est de type « int »
- réelle : est de type « double » (ainsi l’instruction « x1 = 0.45; » avec x1 nombre réel simple précision peut occasionner un warning '=' : truncation from 'const double' to 'float‘).
Les lettres « L », « U » et « F » permettent de préciser le caractère « long », « unsigned » ou « float » d’une constante..
A ces types de base, le C++ ajoute deux autres types de base : « bool » et « wchar_t ».
Il est bien évident, que (contrairement au Fortran) les noms des variables et des constantes sont complétement libres. Certaines lettres ne sont pas considérées par défaut comme entiers ou réels !
La différence entre signés et non signés tient à la plage de valeur que peuvent représenter des variables de ce type. Par exemple un entier signé 16 bits peut représenter des nombres entre -32768 et +32767, alors que non signé la plage de valeur est de 0 à 65535.
Exemple : Exple_07_typesbaseC
Précisions :
Nous verrons le type « bool » en détail plus loin.
En ce qui concerne le type « wchar_t », il s’agit d’une représentation des caractères généralement sur 16 bits ce qui permet d’utiliser le codage Unicode des caractères à la place du codage ASCII (8 bits). Ce codage étendu est nécessaire pour représenter des alphabets non latins et envisager ce que l’on appelle l’internationalisation des programmes.
Il faut utiliser la lettre « L » en préfixe pour spécifier qu’un caractère est étendu (= wide) :
wchar_t w1 = 'x'; wchar_t w2 = '\t'; wchar_t w3 = L'yz'; wchar_t w4 = L'\x77\x34';
Exemple : Exple_08_typesbaseCPP
Note importante :
Le C et le C++ n’ont pas de type de base pour représenter les chaînes de caractères (comme en JAVA le type « string »). Les chaînes de caractères sont représentées par des tableaux de caractères. Il existe cependant dans la librairie standard de C++ une classe std::string, mais il ne s’agit pas d’un type de base, faisant partie du noyau du langage.
La norme ne fixe pas l’implémentation des types de base par les compilateurs, contrairement à JAVA. Il peut donc exister des différences entre les compilateurs.
Ce que la norme impose :
• la taille de char, unsigned char et signed char est de 1 octet
• la taille de wchar_t (signed / unsigned) est supérieure ou égale à celle de char
• la taille de short int (signed / unsigned) est supérieure ou égale à celle de char
• la taille de int (signed / unsigned) est supérieure ou égale à celle de short int
• la taille de long int (signed / unsigned) est supérieure ou égale à celle de int
• la taille de double est supérieure ou égale à celle de float
• la taille de long double est supérieure ou égale à celle de double
wchar_t | ? | char | = 8 bits | ||
long int ? int | ? | short int | ? | char | = 8 bits |
long double | ? | double | ? | float | = Non fixée |
bool | = Non fixée |
Page 31
Précisions :
En principe, le type « int » est de la taille du type natif du processeur utilisé, 32 bits par exemple sur une architecture 32 bits.
Exercice :
- créer un projet Exple_09_sizeof
- dans le programme principal, utiliser la méthode « sizeof » qui retourne la taille d’une variable (d’un objet ou d’un type) pour afficher la taille de plusieurs types de base. Par exemple :
std::cout << sizeof(int) << std::endl;
Reporter ici les tailles :
char = | wchar_t = |
unsigned char = | long = |
signed char = | unsigned long = |
short int = | signed long = |
unsigned short int = | float = |
signed short int = | double = |
int = | long double = |
unsigned int = | bool = |
signed int =
Les littéraux caractères se notent avec des guillemets simples (« quote » en anglais). Eventuellement précédés de « L » pour les caractères longs :
char c1 = 'a';
wchar_t c2 = L'b';
Les caractères inaccessibles au clavier peuvent être fournis grâce à leur code en base 16 (précédé de \x) ou en base 8 (simplement précédé de \) :
char c1 = 'a';
char c2 = L'a';toutes représentationschar c3 = '\141';du caractère‘a’char c4 = '\x61';
Il existe un certain nombre de séquences d’échappement reconnues par le langage C/C++ :
\’ \" \? \\
\a \b \f \n \r \t \v
Page 32
Liste des séquences d’échappement :
newline | \n |
horizontal tab | \t |
vertical tab | \v |
backspace | \b |
carriage return | \r |
form feed | \f |
alert | \a |
backslash \ | \\ |
question mark ? | \? |
single quote ’ | \’ |
double quote " | \" |
Pour représenter les guillemets simples (’) et le backslash (\), la séquence d’échappement correspondante est obligatoire (\’) et (\\) respectivement.
Exercice (facultatif) :
- créer un projet Exple_10_litteraux
- s’exercer à définir quelques exemples de littéraux caractères et les afficher avec std::cout <<
Les littéraux entiers sont des nombres, sans exposant, ni virgule.
• en base décimale (10), les nombres entiers ne peuvent commencer par « 0 »
• en base octale (8), ils doivent commencer par « 0 »
• en base hexadécimale (16), ils doivent commencer par « 0x » ou « 0X »
• les nombres peuvent être précédés d’un opérateur unaire (« - » ou « + »)
unsigned int a1 = 67;
toutes représentations
unsigned int a2 = 0103; du nombre‘67’
unsigned int a3 = 0x43;
Rappel : les suffixes « U » et « L », en minuscules ou majuscules, seuls ou ensembles peuvent être employés pour préciser si l’entier est non signé ou s’il est long.
Page 33
Exemples :
Quelques exemples variés de constantes entières :
long h1 = 12345678L; long h2 = 12345678l; unsigned long h3 = 12345678U; unsigned long h4 = 12345678u; unsigned long h5 = 12345678UL; unsigned long h6 = 12345678ul; unsigned long h7 = 12345678LU; unsigned long h8 = 12345678lu;
Exercice (facultatif) :
- poursuivre le projet précédent Exple_10_litteraux
- s’exercer à définir quelques exemples de littéraux entiers et les afficher avec std::cout <<
Les littéraux flottants sont des nombres réels avec un exposant et/ou une virgule. Les nombres peuvent être précédés d’un signe, opérateur unaire (« - » ou « + ») :
float x1, x2; float x3 = 0.1F;
double y; long double z;
x1 = 0.45; x2 = -3.5e12F; y = 0.45; z = 0.99e-2L;
Rappel : les suffixes « F » et « L », en minuscules ou majuscules, permettent de préciser respectivement que la constante est simple précision (« float ») ou quadruple precision (« long double »). S’il n’y a aucun suffixe, il s’agit d’une constante double précision (« double »).
Page 34
Exercice (facultatif) :
- poursuivre le projet précédent Exple_10_litteraux
- s’exercer à définir quelques exemples de littéraux réels et les afficher avec std::cout <<
En C et C++, les littéraux chaînes de caractères sont définis comme des tableaux de n caractères du type « const char ».
En C et C++, les chaînes de caractères se terminent par le caractère zéro (\0) qui compte dans le nombre de caractères. C’est ce que l’on appelle les chaines de caractères « null terminated » par opposition aux chaînes de la classe string de la librairie standard C++ que nous verrons plus tard.
const char s1[5] = "abcd"; // OKconst char s2[5] = "abcde"; // error: array bounds overflow s1[0] = 'R'; // error: l-value specifies // const object
char s3[5] = "abcd"; // OK s3[0] = 'R'; // OK
Page 35
Précisions :
Il ne faut pas confondre les littéraux, les constantes et les variables :
- littéraux : "abcd" ou 'R'
- constantes : const int I, const char S[5] - variables : int I, char S[5]
Exercice (facultatif) :
- poursuivre le projet précédent Exple_10_litteraux
- s’exercer à définir quelques exemples de littéraux chaînes et les afficher avec std::cout <<
Contrairement à C, le langage C++ dispose d'un type booléen, le type bool, dont les valeurs sont true et false. Les conditions du if, while, do, for et de l'expression conditionnelle ? : sont des expressions de type bool. Les opérateurs relationnels et logiques travaillent sur ce nouveau type.
int i, j, k; bool b;
Pour des raisons de compatibilité avec le C, les conversions implicites entre booléens et types arithmétiques sont conservées. CONSEIL : les éviter |
b = (i>j); // Bien k = (j>i); // A éviter
while (b) // Bien
{
// ...
} | |
if (k) | // A éviter |
...
Page 36
Précisions :
En C, le type booléen n’existe pas. On représente les valeurs « vrai » et « faux » par des entiers. Le zéro signifie « faux » et n’importe quel nombre différent de zéro signifie « vrai ».
Le C++ définit deux « littéraux » booléens : true et false.
Exercice :
- en le compilant, regardez ce que produit le code suivant (Exple_10_litteraux) :
bool b1 = 0; bool b2 = 4; bool b3 = false; bool b4 = true; std::cout << b1 << "\t" << b2 << "\t"
<< b3 << "\t" << b4 << std::endl;
Les identifieurs ou symboles permettent de nommer :
- des classes (class), des structures (struct) ou des unions (union)
- des variables, des constantes, ou des instances de classe
- des types énumérés (enum)
- des attributs de classes
- des fonctions ou des méthodes de classes
- des alias de types (typedef)
- des labels (goto), des macros (#define) ou des paramètres de macros
Un symbole C/C++ est formé d’une suite de lettres (a-z A-Z), de chiffres (0-9) ou de soulignés (underscore_). Le premier caractère d’un symbole est obligatoirement une lettre ou un souligné :
int H1B4_8;
float __abc_1_2; char x1x2x3;
Page 37
Notes :
- le C/C++ est sensible à la casse minuscules/majuscules des caractères (filename et FileName sont deux symboles différents).
- les symboles ne peuvent être des mots-clés du langage (int et float par exemple)
- il est déconseillé d’utiliser des symboles commençant par deux soulignés (__) ou un souligné suivi d’une lettre majuscule (cf. la norme C++).
Ce que dit la norme C++ :
17.4.3.1.2 Global names
Certain sets of names and function signatures are always reserved to the implementation:
— Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
Exemple : Exple_11_symboles
Définir une variable, une classe ou une fonction c’est lui donner un type, des attributs ou un corps de fonction. La définition est unique.
Tous les symboles utilisés pour compiler un fichier doivent être déclarés. La déclaration peut consister à définir le symbole en question ou à rappeler des symboles ailleurs.
// CI-DESSOUS, DES DEFINITIONS, SAUF UNE DECLARATIONint a; // definit aextern const int b = 1; // definit bint f(int x) { return x+a; } // definit f et definit xstruct S { int a; int b; }; // definit S, S::a, et S::b
struct T // definit T
{ int t; // definit l'attribut d'instance T::tstatic int a; // declare l'attribut de classe T::a T(): t(0) { } // definit un constructeur de T