#include <iostream> int fact(int n) { if (n==1) return 1; else return n*fact(n-1); } int main () { int a = 5; cout << "fact(" << a << ") = " << fact(a) << endl; return 0; }
Au moment où la fonction main fait l'appel fact(a), n reçoit la valeur de a, qui est 5. Plaçons un point d'arrêt sur la fonction fact et lançons le programme avec r, le programme est interrompu à chaque appel à fact au niveau de la ligne << if (n==1) return 1; >>. Avançons avec step dans l'exécution de la fonction fact, après 3 appels récursifs (à elle-même), examinons la pile d'appel avec backtrace :
(gdb) bt #0 fact (n=3) at fact.c:5 #1 0x10708 in fact (n=4) at fact.c:6 #2 0x10708 in fact (n=5) at fact.c:6 #3 0x10748 in main () at fact.c:12La pile a 4 niveaux : les 3 appels à fact et l'appel à main.
Au niveau courant (noté 0), tentons d'imprimer la valeur de la variable a :
(gdb) p a No symbol "a" in current context.La variable a n'est pas définie dans ce contexte. Nous pouvons remonter dans la pile avec la commande up. Si nous allons jusqu'au niveau 3 (appel à main) avec 3 << up >> et que nous tentons à nouveau d'imprimer la valeur de a, nous obtenons :
(gdb) p a $3 = 5Dans le contexte d'appel à main, la variable a est bien définie.
L'analyse au débogueur du contexte (ou environnement) d'exécution d'une fonction permet de mieux comprendre le mode de fonctionnement de C++.
Mémento C - shell, Emacs, gdb
Programme |
int main() |
{ |
... |
return 0; |
} |
Objets |
int i; |
double x, y; |
char c; |
char s[32]; |
char a[3][3]; |
Constantes |
const int N=10; |
Fonctions |
Définition |
---|
double f(int i, int j, double x) |
{ |
int k,l |
double y,z; |
... |
return z; |
} |
void g(int i) |
{ |
if (i==2) { |
return; |
} |
... |
} |
Déclaration |
void g(int i); |
Passage par référence |
void max(double x, double y, |
double& z) |
{ |
if (x<y) |
z = y; |
else |
z = x; |
} |
... |
max(x, y, z); |
... |
Portées |
// variable globale |
int a; |
// paramètres |
void hop(int b, int c) |
{ |
// variables locales |
int i, j; |
// variable statique |
static int memo; |
} |
Initialisations |
int globale=3; |
|
void hop() |
{ |
int locale=2; |
static int statique=4; |
complexe z={1,2}; |
double tb[2]={3,4}; |
int a[]={2,4}; |
int b[][3]={{1,2,3},{4,5,6}}; |
complexe c[]={{1,2},{3,4}}; |
} |
Conditions |
if ( test) { |
... |
} |
if ( test) { |
... |
} else { |
... |
} |
switch (i) { |
case 1: |
... |
break; |
case 2: |
... |
break; |
default: |
... |
} |
Tests | |
égal | == |
différent | != |
supérieur | > et >= |
inférieur | < et <= |
et | && |
ou | || |
non | ! |
Boucles |
for (i=1;i<=n;i=i+1) { |
... |
} |
while (i<j) { |
... |
} |
do { |
... |
} while (i<j); |
Structures |
struct complexe{ |
double re; |
double im; |
}; |
complexe z; |
z.re=2; |
z.im=3; |
struct list { |
int val; |
list *next; |
}; |
enum direction { |
Nord, Est, Sud, Ouest}; |
Contractions | |
i=i+1; | i++; |
(*c).a | c->a |
&(*i) | i |
Maths |
#include <cmath> |
Tableaux |
void remplit(int t[]) |
{ |
int i; |
for (i=0;i<10;i++) |
t[i]=2*i+1; |
} |
... |
int tb[10]; |
remplit(tb); |
for (i=0; i<10; i++) |
cout << "tb[" << i << "]=" << i << endl; |
... |
Tableaux multidim |
// Déclaration des dimensions obligatoire |
// à partir de la deuxième |
void remplit(int t[][5]) |
{ |
int i,j; |
for (i=0;i<10;i++) |
for (j=0;j<5;j++) |
t[i][j]=2*i+j; |
} |
... |
int tb[10][5]; |
remplit(tb); |
for (i=0;i<10;i++) |
for (j=0;j<5;j++) |
cout<<"tb["<<i<<"]["<<j<<"]="<<tb[i][j]<<endl; |
... |
Tableaux dynamiques |
void remplit(int n, int t[]) |
{ |
... |
} |
|
int main() |
{ |
int *t; |
int n; |
|
cin >> n; |
t=new int[n]; |
remplit(n, t); |
... |
delete[] t; |
} |
Abréviations de type |
typedef int data; |
typedef double vecteur[N]; |
typedef tree_cell *tree; |
typedef double (*fun)(double); |
Entrées/Sorties |
#include <iostream> |
cout << i << x << c << s; |
cin >> i >> x >> c >> s; |
program < data > out |
#include <fstream> |
|
ifstream in("data"); |
if (!in) { |
cerr << "erreur de lecture\n"; |
exit(1); |
} |
in >> i >> x >> c >> s; |
in.close(); |
ofstream out("out"); |
if (!out) { |
cerr << "erreur d'écriture\n"; |
exit(1); |
} |
... |
out << "Résultats: " << n << '\t' << y << endl; |
... |
out.close(); |
#include <cstdlib> |
|
int main(int argc, char argv[]) |
{ |
string name; |
int n; |
double x; |
|
if (argc != 4) { |
cout << "Syntax: " << argv[0] << " name n x\n"; |
exit(1); |
} |
name = argv[1]; |
n=atoi(argv[2]); |
x=atof(argv[3]); |
... |
} |
Arithmétique | |
Modulo | j=i%n |
(attention -7%5 vaut -2) |
|
Division réelle | x=double(i)/j; |
x=i/2.0; |
Caractères |
char c; |
cin >> c; |
c='a'; |
cout << c; |
Chaînes |
#include <string> |
string s; |
cin >> s; |
cout << s; |
c=s[i]; |
s[i]='a'; |
l=s.length(); |
dest = source; |
if(s1 == s2) ... |
Makefile |
LDLIBS=... |
Commandes Emacs (C) | |
Compiler | CTRL-c CTRL-c |
Erreur suivante | CTRL-c CTRL-n |
Erreur précédente | CTRL-c CTRL-p |
Tuer la compilation | CTRL-c CTRL-k |
Indenter | TAB |
; sans nouvelle ligne | MÉTA-; |
} sans nouvelle ligne |
MÉTA-} |
Panique! | CTRL-g |
compléter un nom de fichier | TAB |
Lancer gdb | M-X gdb fichier |
Souris | |
Recopier | |
1- Début | Clic gauche |
2- Fin | Clic droit |
3- Copier | Clic mileu |
Commandes shell Unix | |
Lister | ls |
Créer un répertoire | mkdir Info |
Changer de répertoire | cd Info |
Remonter | cd .. |
Retourner chez soi | cd |
Aller chez quelqu'un | cd ~joe |
Copier un fichier | cp hop.c hip.c |
Copier des fichiers | cp ~joe/*.c . |
Renommer un fichier | mv hop.c hip.c |
Renommer un répertoire | mv info Info |
Déplacer un fichier | mv hop.c Info |
Déplacer des fichiers | mv *.c Info |
Détruire un fichier | rm hop.c |
Détruire des fichiers | rm *.c |
Détruire un répertoire | rmdir Info |
Compléter | TAB |
Imprimer un fichier | lpr hop.c |
Surveiller l'impression | lpq |
Supprimer une impression | lprm joe |
Graphiques |
#include <win> |
winInit(w,h,col); |
winLoop(); |
winLine(a,b,c,d,col,t); |
winRect(a,b,w,h,col,t); |
winFillRect(a,b,w,h,col); |
winCircle(a,b,w,h,col,t); |
winFillCircle(a,b,w,h,col); |
winPoint(a,b,col); |
void winPoly(int n,pixel p[],WinColor col,int w); |
void winFillPoly(int n,pixel p[],WinColor col); |
winString(a,b,s,col); |
winGreyImage(g,w,h,x,y); |
winColorImage(r,g,b,w,h,x,y); |
winGreyPoint(x,y,g); |
winColorPoint(x,y,r,g,b); |
button=winInput(x,y); |
key=winKey(); |
key=winEvent(millisec, ev); |
white,black,blue,red,green,yellow,cyan,magenta |
LDLIBS=-lwin -lXm -lXt -lX11 |
Commandes gdb | ||
Aide en ligne | help | générale |
help <sujet> | spécifique | |
Charger un programme | file <fichier> | |
Lancer l'exécution | r(un) | |
Lister | l(ist) | 10 lignes suivantes |
l(ist) <n![]() |
10 lignes autour | |
l(ist) <fonction> | ||
Interrompre l'exécution | kill | abandonner l'exécution |
b(reak) <n![]() |
placer un point d'arrêt | |
sur une ligne | ||
b(reak) <fonction> | placer un point d'arrêt | |
à l'entrée d'une fonction | ||
info b | lister les points d'arrêt | |
delete <n![]() |
supprimer un point d'arrêt | |
CTRL-C | interrompre (dans xterm) | |
CTRL-C CTRL-C | interrompre (dans Emacs) | |
l'exécution | ||
Afficher une expression | p(rint) <expr> | valeur courante |
display <expr> | valeur à chaque arrêt | |
Relancer l'exécution | c(ont) | jusqu'au prochain point d'arrêt |
s(tep) | d'une instruction | |
n(ext) | d'une instruction (même niveau) | |
finish | pour terminer un niveau | |
until <n![]() |
jusqu'à la ligne | |
Naviguer dans la pile | up | monter d'un niveau |
down | descendre d'un niveau | |
fr(ame) <n![]() |
aller à un niveau donné | |
bt (backtrace) | afficher la pile |
Emacs (Raccourcis clavier) | ||
charger/sauver | charger | CTRL-x CTRL-f |
sauvegarder | CTRL-x CTRL-s | |
sauvegarder sous (save as) | CTRL-x CTRL-w | |
quitter | CTRL-x CTRL-c | |
manipuler | changer de tampon | CTRL-x b |
les tampons | détruire un tampon | CTRL-x k |
manipuler | couper la fenêtre en deux | CTRL-x 2 |
les fenêtres | passer à une autre fenêtre | CTRL-x o |
faire occuper tout Emacs à une fenêtre | CTRL-x 1 | |
faire disparaître une fenêtre | CTRL-x 0 | |
se déplacer | un caractère à droite (forward) | CTRL-f ou |
flèche à dr. | ||
un mot à droite | MÉTA-f ou | |
SHIFT-fl. à dr. | ||
un caractère à gauche (backward) | CTRL-b ou | |
flèche à g. | ||
un mot à gauche | MÉTA-b ou | |
SHIFT-fl. à g. | ||
ligne suivante (next) | CTRL-n ou | |
flèche bas | ||
ligne précédente (previous) | CTRL-p ou | |
flèche haut | ||
début de ligne | CTRL-a ou Home | |
fin de ligne | CTRL-e ou End | |
phrase précédente | MÉTA-a | |
phrase suivante | MÉTA-e | |
page suivante | CTRL-v ou PgUp | |
page précédente | CTRL-MÉTA-v ou PgDown | |
début du tampon | MÉTA-![]() |
|
fin du tampon | MÉTA-![]() |
|
centrer la ligne courante | CTRL-l |
Emacs (Raccourcis clavier, suite) | ||
effacer | un caractère à gauche | BackSpace |
un caractère à droite | CTRL-d ou Delete | |
la fin d'une ligne | CTRL-k | |
une région sélectionnée | CTRL-w | |
mode remplacement | Insert | |
chercher | chercher vers l'avant du texte | CTRL-s |
chercher vers l'arrière du texte | CTRL-r | |
remplacer | remplacer | MÉTA-% |
copier/coller | copier | MÉTA-w |
détruire et copier | CTRL-w | |
coller | CTRL-y | |
insérer un fichier | CTRL-x i | |
manipuler les | appeler une commande | MÉTA-x |
commandes | annuler la dernière commande | CTRL-x u |
répéter une commande | CTRL-u | |
aide | liste des commandes contenant | CTRL-h a |
un mot écrit dans le minibuffer | ||
liste des commandes accessibles | CTRL-h b | |
par une combinaison de touches | ||
consultation du manuel | CTRL-h i | |
description de la commande exécutée | CTRL-h k | |
par une combinaison de touches | ||
description d'une commande | CTRL-h f | |
écrite dans le minibuffer | ||
description du mode majeur | CTRL-h m | |
de la fenêtre courante | ||
tutorial | CTRL-h t | |
liste des options du help | CTRL-h h | |
description des options du help | CTRL-h CTRL-h | |
doc d'une fonction | MÉTA-x man |