Cours de Fortran 90/95 et C
Table des matières
1 Introduction 16
1.1 Programmation en langage compilé . . . . . 16
1.2 Historique 18
1.2.1 Langage fortran 18
1.2.2 Langage C . . 19
1.3 Intérêts respectifs . . 20
1.4 Généralités . . . . . 21
1.5 Exemple de programme C avec une seule fonction utilisateur . . . . . 22
1.6 Exemple de programme fortran avec une seule procédure 23
1.7 Structure générale d’un programme C . . . . 24
1.8 Exemple de programme C avec deux fonctions 26
1.9 Structure générale d’un programme fortran . . 28
1.10 Exemple de programme fortran avec un module . . . . . 31
1.11 Compilation et édition de liens . . 33
1.12 Compilateurs utilisés . 36
2 Types et déclarations des variables 37
2.1 Types de base . . . . 37
2.2 Domaine et précision . 39
2.2.1 Domaine des entiers signés 39
2.2.2 Domaine et précision des flottants . . . 41
2.2.3 Valeurs maximales des entiers en C . . 42
2.2.4 Caractéristiques des types numériques en fortran . 45
2.3 Déclarations des variables . . . . 47
2.4 Exemples d’attribut constante . . 49
2.4.1 Exemples d’attribut const en C . . . 49
2.4.2 Exemples d’attribut parameter en fortran . . . 49
2.5 Les constantes . . . . 51
3 Opérateurs52
3.1 Opérateur d’affectation 52
3.2 Opérateurs algébriques . . . . . 54
3.3 Opérateurs de comparaison . . . 54
3.4 Opérateurs logiques . 55
3.5 Incrémentation et décrémentation en C . . . . 57
3.6 Opérateurs d’affectation composée en C . . . 58
3.7 Opérateur d’alternative en C . . . 58
3.8 Opérateurs agissant sur les bits . 59
3.9 Opérateur sizeof en C 60
3.10 Opérateur séquentiel «,» en C . . 60
3.11 Opérateurs & et * en C . . . . . 60
3.12 Priorités des opérateurs en C . . . 61
4 Entrées et sorties standard élémentaires 62
4.1 Introduction aux formats d’entrée–sortie . . . 63
4.1.1 Introduction aux formats en C . . . . . 66
5 Structures de contrôle 68
5.1 Structure conditionnelle if . . . 69
5.1.1 Condition if . 69
5.1.2 Alternative if else . . 69
5.1.3 Exemples d’alternative if else . . 71
5.1.4 Alternatives imbriquées if else . 73
5.1.5 Cas de else if en fortran . . . . . 74
5.2 Aiguillage avec switch/case 75
5.2.1 Exemples d’aiguillage case . . . . . 76
5.3 Structures itératives ou boucles . . 81
5.3.1 Exemples de boucle for ou do . . . 84
5.4 Branchements ou sauts . . . . . 87
5.4.1 Exemples de bouclage anticipé cycle/continue . . . . . 89
5.4.2 Exemple de sortie de boucle break/exit . . . 90
6 Introduction aux pointeurs93
6.1 Intérêt des pointeurs . 93
6.2 Pointeurs et variables : exemple du C . . . . . 94
6.2.1 Affectation d’un pointeur en C . . . . . 97
6.2.2 Indirection (opérateur ? en C) . . . . . 99
6.3 Pointeurs en fortran . 103
6.4 Syntaxe des pointeurs (C et fortran) . . . . . 104
6.5 Tailles des types de base et adresses en C . . 105
6.6 Initialiser les pointeurs ! 107
7 Procédures : fonctions et sous-programmes 110
7.1 Généralités . . . . . 110
7.1.1 Structure d’un programme C . . . . . 112
7.1.2 Structure générale d’un programme fortran . . . . 114
7.1.3 Fonctions renvoyant une valeur . . . . 116
7.1.4 Sous-programmes et fonctions C sans retour . . . 119
7.1.5 Passage des arguments : nécessité des pointeurs en C . . . . 120
7.1.6 Vocation des arguments en fortran . . 121
7.2 Exemples de procédures . . . . . 122
7.2.1 Faux échange en C . . . . 122
7.2.2 Vrai échange avec pointeurs en C . . . 125
7.2.3 Procédure de module en fortran 90 . . 128
7.3 Durée de vie et portée des variables . . . . . 130
7.3.1 Exemples de mauvais usage des variables locales . 133
7.3.2 Exemples de variable locale permanente . . . . . 135
7.3.3 Exemples d’usage de variable globale . 137
7.4 Visibilité des interfaces et compilation séparée 139
7.5 Compléments sur les procédures . 142
7.5.1 Exemples de procédures récursives : factorielle . . 143
7.5.2 Les fonctions mathématiques . . . . . 152
7.5.3 Une erreur classique : la fonction abs en flottant en C . . . . 156
8 Tableaux 157
8.1 Définition et usage . . 157
8.2 Tableaux de dimension fixe . . . . 158
8.3 Tableaux en fortran . . 160
8.3.1 Opérations globales sur les tableaux en fortran . . 161
8.3.2 Sections régulières de tableaux en fortran . . . . . 161
8.3.3 Fonctions opérant sur des tableaux en fortran . . . 162
8.3.4 Parallélisation en fortran . . 165
8.3.5 Ordre des éléments de tableaux 2D en fortran . . . 165
8.4 Tableaux et pointeurs et en C . . . 169
8.4.1 Ordre des éléments de tableaux 2D en C . . . . . 170
8.4.2 Sous-tableau 1D avec un pointeur . . . 173
8.4.3 Utilisation de typedef . 175
8.5 Procédures et tableaux 176
8.5.1 Passage d’un tableau 1D en fortran . . 177
8.5.2 Passage d’un tableau 2D en fortran . . 179
8.5.3 Passage d’un tableau 1D en C . . . . 181
8.5.4 Passage d’un tableau 2D en C (norme C89) . . . . 183
8.5.5 Passage d’un tableau 2D de dimensions variables en C99 . . . 187
8.5.6 Tableaux automatiques locaux : C99 et fortran . . . 190
9 Allocation dynamique 191
9.1 Introduction . . . . . 191
9.1.1 Trois types de tableaux . . 191
9.1.2 Cycle élémentaire d’un tableau dynamique . . . . 192
9.1.3 Allocation dynamique en C avec malloc ou calloc . . . . 194
9.1.4 Libération de la mémoire allouée en C avec free 196
9.2 Allocation d’un tableau 1D . . . . 197
9.2.1 Allocation d’un tableau 1D en fortran . 197
9.2.2 Allocation d’un tableau 1D en C . . . . 198
9.3 Risques de fuite de mémoire . . . 200
9.3.1 Fuite de mémoire avec les pointeurs en fortran . . 200
9.3.2 Fuite de mémoire en C . . 201
9.4 Application : manipulation de matrices . . . . 202
9.4.1 Matrices de taille quelconque en fortran 202
9.4.2 Matrices de taille quelconque en C . . 205
9.5 La bibliothèque libmnitab . . 212 9.6 Allocation dynamique en fortran 2003 . . . . . 213
10 Chaînes de caractères217
10.1 Introduction . . . . . 217
10.2 Déclaration, affectation des chaînes de caractères . . . . 218
10.3 Manipulation des chaînes de caractères . . . 219
10.4 Chaînes de caractères en C . . . 221
10.4.1 Déclaration de chaînes de longueur fixe en C . . . 223
10.5 Exemple de chaînes de caractères de taille quelconque . . 226
10.5.1 Longueur d’une chaîne avec strlen et opérateur sizeof . 229
10.5.2 Concaténation de chaînes avec strcat . . . . . 230
10.5.3 Caractères non-ascii en C99 : caractères étendus et multi-octets233
10.6 Chaînes de caractères en fortran . 234
10.6.1 Sous-chaînes en fortran . . 234
10.6.2 Fonctions manipulant des chaînes en fortran . . . 234
10.6.3 Tableaux de chaînes en fortran . . . . 235
10.6.4 Entrées-sorties de chaînes en fortran . 236
10.6.5 Allocation dynamique de chaînes en fortran 2003 . 236
10.6.6 Passage de chaînes en argument en fortran . . . . 237
11 Entrées–sorties 238
11.1 Type de fichiers et accès : avantages respectifs 238
11.2 Entrées-sorties binaires (ou non formatées) . . 240
11.3 Entrée-sorties formatées (fichiers codant du texte) . . . . 241
11.4 Formats d’entrée–sortie . . . . . 244
11.5 Exemple de lecture de fichier formaté en C . . 246
11.6 Exemple d’écriture de tableau 1D en fortran . 248
12 Structures ou types dérivés 251
12.1 Intérêt des structures . 251
12.2 Définition, déclaration et initialisation des structures . . . . 253
12.2.1 Définition de structures/types dérivés . 253
12.2.2 Déclaration et initialisation d’objets de type structure 254
12.2.3 Contraintes d’alignement dans les structures en C . 255
12.2.4 Implémentation des types dérivés en fortran . . . . 256
12.3 Manipulation des structures . . . 257
12.4 Structures et tableaux 260
12.5 Structures/types dérivés, pointeurs et procédures . . . . . 261
12.6 Exemple de structures auto-référencées : listes chaînées . 266
12.7 Structures à composantes dynamiques . . . . 270
12.8 Conclusion sur les structures . . . 272
13 Compilation séparée 273
13.1 Intérêt de la compilation séparée . 273
13.2 Mise en œuvre robuste de la compilation séparée . . . . . 273
13.3 Fichiers d’entête (header files) en C . . . . . 278
13.3.1 Définition et usage . . . . 278
13.3.2 Structure d’un fichier d’entête . . . . . 279
13.4 Exemple de programme C en plusieurs fichiers 280
13.5 Bibliothèques de fichiers objets . . 283
13.5.1 Bibliothèques statiques et bibliothèques dynamiques . . . . . 283
13.6 Commande de gestion des bibliothèques statiques : ar . 284
13.6.1 Création d’une bibliothèque statique (archive) . . . 285
13.6.2 Utilisation d’une bibliothèque statique (entête et archive) . . . . 286
13.6.3 Retour sur la bibliothèque standard du C . . . . . 287
13.6.4 Retour sur la bibliothèque libmnitab . . . . . 288
13.6.5 Bilan sur la création et l’usage d’une bibliothèque statique . . . 289
13.7 Génération d’un fichier exécutable avec make 290
13.7.1 Principe . . . . 290
13.7.2 Construction d’un makefile . . . . 291
13.7.3 Exemple élémentaire de makefile en C . . . . 292
13.7.4 Utilisation d’un makefile . . . . . 294
1 Introduction
1.1 Programmation en langage compilé
Conception, écriture et exécution d’instructions destinées à être traitées de manière automatique par un ordinateur.
Étapes (itérer si nécessaire) :
– conception : définir l’objectif du programme et la méthode à utiliser
? algorithme puis organigramme puis pseudo-code
– codage : écrire le programme suivant la syntaxe d’un langage de haut niveau, portable et utilisant des bibliothèques : C, fortran,
? code source : fichier texte avec instructions commentées compréhensible pour le concepteur et les autres
– compilation : transformer le code source en un code machine ? code objet puis code exécutable : fichiers binaires compréhensibles par la machine
– exécution : tester le bon fonctionnement du programme
? exploitation du code et production des résultats
1.1 Programmation en langage compilé
– L’ordinateur est muni d’un système d’exploitation (exemple : linux)
– Le code source est écrit dans un fichier texte au moyen d’un éditeur de texte.
Exemples : vi, emacs, kate, kwrite, sous linux.
– Le code machine (fichier objet ou exécutable) généré par un compilateur : programme qui analyse le code source, signale les erreurs de syntaxe, produit des avertissements sur les constructions suspectes, convertit un code source en code machine, optimise le code machine, résout les appels aux bibliothèques
Exemples :
– Les instructions du programme sont exécutées par un processeur caractérisé par son architecture, la taille de ses registres (nombre de bits traités ensemble :
32, 64 bits), sa vitesse d’horloge, son jeu d’instructions
Exemples : famille x86 d’Intel (32 bits), Pentium (32/64 bits) ou x64 (64 bits)
1.2 Historique
1.2 Historique
1.2.1 Langage fortran : Fortran = Formula Translation
– 1954 : premier langage de calcul scientifique (télétypes, puis cartes perforées, ) –
– 1978 : fortran V ou fortran 77
– 1991 : fortran 90 (évolution majeure mais un peu tardive) format libre, fonctions tableaux, allocation dynamique, structures, modules ? ne plus écrire de fortran 77
– 1995 : mise à jour mineure
– 2004 : fortran 2003 standard adopté nouveautés : interopérabilité avec C, arithmétique IEEE, accès au système, allocations dynamiques étendues à d’autres contextes, aspects objet fortran 2003 en cours d’implémentation sur les compilateurs
– 2010 : standard fortran 2008 adopté le 20 sept 2010
1.2 Historique
1.2.2 Langage C
– langage conçu dans les années 1970
– 1978 : parution de The C Programming Langage de B. KERNIGHAN et D. RICHIE
– développement lié à la diffusion du système UNIX
– 1988–90 : normalisation C89 ANSI–ISO (bibliothèque standard du C)
Deuxième édition du KERNIGHAN et RICHIE norme ANSI
– 1999 : norme C99, implémentation nouveaux types (booléen, complexe, entiers de diverses tailles (prise en compte des processeurs 64 bits), caractères larges (unicode), ), introduction de la généricité dans les fonctions numériques, déclarations tardives des variables, tableaux automatiques de taille variable
? se conformer à une norme pour la portabilité
– future norme C11 (ex-C1x) parue en avril 2011 (généricité via cpp, unicode, )
– base d’autres langages dont le C++ (premier standard en 1998) puis java, php,
1.4 Généralités
|
langage C |
langage Fortran |
|
|
format «libre» |
format |
format libre du fortran 90 (format fixe en fortran 77) |
|
? mettre en évidence les structures par la mise en page (indentation) |
||
|
pas une entité particulière (la fin de ligne est un séparateur comme l’espace, la tabulation, ) |
ligne |
la fin de ligne termine une instruction & en fin de ligne permet de continuer une instruction sur la ligne suivante |
|
instructions simples terminées par ; |
; |
; pour séparer plusieurs instructions sur une même ligne |
|
entre /* et */ (peut s’étendre sur plusieurs lignes) (pas d’imbrication selon la norme) en C99 et C++ introduit par // et terminé en fin de ligne |
commentaire |
introduit par ! et terminé en fin de ligne |
|
lignes de directives pour le préprocesseur : # en première colonne |
||
|
identificateur : au plus 31 caractères alphanumériques plus _,commençant par une lettre ou _ |
||
|
distinction |
maj/minuscule |
pas de distinction |
Fortran et C 1.5 Exemple de programme C avec une seule fonction utilisateur
1.6 Exemple de programme fortran avec une seule procédure
programppal ! << début du programme ppal
implicit none ! nécessaire en fortraninteger:: i! déclarations
integer:: s = 0
doi = 1, 5 ! structure de boucles = s + i
end do ! <<= fin de bloc
write(*,*)"somme des entiers de 1 à 5"write(*,*)"somme = ", s
stop ! ne renvoie pas de status
end programppal ! << fin du programme ppal
1.7 Structure générale d’un programme C
1.7 Structure générale d’un programme C
#include
#include "fonction.h"
intmain( ) { void
Déclarations des variables
Instructions exécutables
}
Structure élémentaire d’un programme C89
1.7 Structure générale d’un programme C
– Une instruction simple doit se terminer par ;
– Une instruction composée, délimitée par des accolades { et } est constituée d’un bloc d’instructions simples ou composées (imbrication possible)
– La définition d’une fonction se compose d’un entête et d’un corps (entre { et }) qui est en fait une instruction composée.
– L’entête d’une fonction spécifie le type de la valeur de retour, le nom de la fonction et ses paramètres ou arguments avec leurs types :
type valeur_de_retour (type1 arg1, type2 arg2, )
où chaque argument est déclaré par son type, suivi de son identificateur
– Un programme C = une ou plusieurs fonctions dont au moins la fonction main : le programme principal.
N.-B : à l’extérieur de ces fonctions, il peut comporter des déclarations de variables, des déclarations de fonctions spécifiant leur prototype (interface en fortran), et des directives pour le préprocesseur introduites par #.
1.8 Exemple de programme C avec deux fonctions
1.8 Exemple de programme C : 2 fonctions : main et somme
/* programme elem.c */
/* instructions préprocesseur */
#include /* pour les entrées/sorties */
#include /* par exemple pour exit */ /* fin des instructions préprocesseur */int somme(const int p); /* déclaration de la fonction somme */intmain(void)/* fonction principale (sans param.)*/
{/* <<= début de bloc */int s ;/* déclaration de l’entier s */
printf("somme des entiers de 1 à 5\n");/* avec retour ligne => "\n" */s = somme(5) ; /* appel de la fonction somme */printf("somme = %d\n", s) ; /* impression du résultat */exit(0) ; /* renvoie à unix un status 0 (OK) */
} /* <<= fin de bloc */
... ... ...
1.11 Compilation et édition de liens
– Fichier source (texte) de suffixe .c en C (.f90 en fortran 90)
– Fichier objet (binaire) de suffixe .o
– Fichier exécutable (binaire) a.out par défaut
La commande de compilation gcc toto.c (gfortran/g95 toto.f90) lance par défaut trois actions :
1. traitement par le préprocesseur (cpp) des lignes commençant par #
appelées directives (transformation textuelle)
2. compilation à proprement parler ? fichier objet .o
3. édition de liens (link) : le compilateur lance ld ? fichier exécutable a.out assemblage des codes objets et résolution des appels aux bibliothèques
N.-B. : seul le fichier source est portable (indépendant de la machine)
Options de compilation
Options de compilation permettant de choisir les étapes et les fichiers :
? gcc -E toto.c : préprocesseur seulement
? -c : préprocesseur et compilation seulement
? -o toto.x : permet de spécifier le nom du fichier exécutable
? -ltruc donne à ld l’accès à la bibliothèquelibtruc.a
(ex. : -lm pour libm.a, bibliothèque mathématique indispensable en C) Options de compilation utiles à la mise au point :
? vérification des standards du langage (-std=c99 ou -std=f95)
? avertissements (warnings) sur les instructions suspectes (variables non utilisées, instructions apparemment inutiles, changement de type, )
? vérification des passages de paramètres
(nécessite un contrôle interprocédural, donc les protoypes ou interfaces) ? faire du compilateur un assistant efficace pour anticiper les problèmes avant des erreurs à l’édition de liens ou, pire, l’exécution.
2.2.3 Valeurs maximales des entiers en C
Définies dans /usr/include/limits.h
(et /usr/include/stdint.h en C99)
Le code d’impression C99 par curiosité :
#include // limites-int-machine-c99.c
#include
#include#includeintmain(void){
// impression des valeurs limites des entiers sur la machine
// non-signés puis signés en décimal, hexadécimal et octal
// version C99
/* entier long long */ // C99 seulementprintf("%-18s %20llu %16llx %22llo\n",
"Unsig-Lng-Lng-max", UINTMAX_MAX, UINTMAX_MAX, UINTMAX_MAX);printf("%-18s %20lld %16llx %22llo\n",
"Long-Long-max", LLONG_MAX, LLONG_MAX, LLONG_MAX);
/* entier long */
printf("%-18s %20lu %16lx %22lo\n",
"Unsigned-Long-max", ULONG_MAX, ULONG_MAX, ULONG_MAX);printf("%-18s %20ld %16lx % 22lo\n",
"Long-max", LONG_MAX, LONG_MAX, LONG_MAX);
/* entier */
printf("%-18s %20u %16x % 22o\n",
"Unsigned-Int-max", UINT_MAX, UINT_MAX, UINT_MAX);printf("%-18s %20d %16x % 22o\n",
"Int-max", INT_MAX, INT_MAX, INT_MAX);
/* entier court */
printf("%-18s %20hu %16hx % 22ho\n",
"Unsigned-Short-max", USHRT_MAX, USHRT_MAX, USHRT_MAX);printf("%-18s %20hd %16hx % 22ho\n",
"Short-max",SHRT_MAX, SHRT_MAX, SHRT_MAX);exit(0);
}
Valeurs maximales des entiers en C : machine 32 bits
Unsig-Lng-Lng-max 18446744073709551615 ffffffffffffffff 1777777777777777777777
Long-Long-max 9223372036854775807 7fffffffffffffff 777777777777777777777
|
Unsigned-Long-max |
4294967295 |
ffffffff |
37777777777 |
|
Long-max |
2147483647 |
7fffffff |
17777777777 |
|
Unsigned-Int-max |
4294967295 |
ffffffff |
37777777777 |
|
Int-max |
2147483647 |
7fffffff |
17777777777 |
|
Unsigned-Short-max |
65535 |
ffff |
177777 |
|
Short-max |
32767 |
7fff |
77777 |
Valeurs maximales des entiers en C : machine 64 bits
Unsig-Lng-Lng-max 18446744073709551615 ffffffffffffffff 1777777777777777777777
Long-Long-max 9223372036854775807 7fffffffffffffff 777777777777777777777
Unsigned-Long-max 18446744073709551615 ffffffffffffffff 1777777777777777777777
Long-max 9223372036854775807 7fffffffffffffff 777777777777777777777
|
Unsigned-Int-max |
4294967295 |
ffffffff |
37777777777 |
|
Int-max |
2147483647 |
7fffffff |
17777777777 |
|
Unsigned-Short-max |
65535 |
ffff |
177777 |
|
Short-max |
32767 |
7fff |
77777 |
2.2.4 Caractéristiques des types numériques en fortran
|
DIGITS(x) |
nombre de bits de |x| si entier, de sa mantisse si réel |
|
PRECISION(x) |
nombre de chiffres (décimaux) significatifs de x |
|
EPSILON(x) |
plus grande valeur du type de x négligeable devant 1 |
|
RANGE(x) |
puissance de 10 du domaine de x (plus petite valeur absolue) |
|
TINY(x) |
plus petite valeur positive représentable dans le type de x |
|
HUGE(x) |
plus grande valeur positive représentable dans le type de x |
Portabilité numérique du code
? demander la variante (KIND) du type numérique suffisante ki = SELECTED_INT_KIND(r) pour les entiers allant jusqu’à 10r kr = SELECTED_REAL_KIND(p,r) pour les réels
pour un domaine de 10?r à 10r et une précision 10?p (p chiffres significatifs) Entiers par défaut
|
compil/proc. |
option |
KIND |
DIGITS |
HUGE |
|
g95/32 bits |
-i4 |
4 |
31 |
2147483647 = 231 ? 1 |
|
g95/64 bits |
-i8 |
8 |
63 |
9223372036854775807 = 263 ? 1 |
Réels par défaut
|
option g95 |
nb. octets |
Digits |
Préc. |
EPSILON |
TINY |
HUGE |
|
-r4 |
4 |
24 |
7 |
1.192093E-7 |
1.175494E-38 |
3.402823E+38 |
|
-r8 |
8 |
53 |
15 |
2.220 E-016 |
2.225 E-308 |
1.79769 E+308 |
2.3 Déclarations des variables
2.3 Déclarations des variables
Déclarer une variable = réserver une zone en mémoire pour la stocker
Variable typée ? lui associer un codage : transformation entre valeur et état des bits en mémoire vive
La taille de la zone et le codage dépendent du type de la variable.
Les bits de la zone ont au départ des valeurs imprévisibles sauf si
Initialiser une variable = affecter une valeur à une variable au moment de la réservation de la mémoire
Déclarer en tête des procédures : obligatoire en fortran et conseillé en C89
En C99 : déclarations tardives autorisées mais préférer en tête de bloc
