#include <stdio.h>
int fact(int n)
{
if (n==1) return 1;
else return n*fact(n-1);
}
int main ()
{
int a = 5;
printf("fact(%d)=%d\n",a,fact(a));
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:12
La 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 = 5
Dans 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
| 1|c|Programme |
|---|
int main() |
{ |
... |
return 0; |
} |
| 1|c|Variables |
|---|
int i; |
double x,y; |
char c; |
char s[32]; |
char A[3][3]; |
| 1|c|Constantes |
|---|
const int n=10; |
#define N 10 |
enum {NORD,EST,SUD,OUEST}; |
| 1|c|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); |
| 1|c|Types de variables |
|---|
/* variable globale */ |
int a; |
/* parametres */ |
void hop(int b,int c) |
{ |
/* variables locales */ |
int i,j; |
/* variable statique (conserve |
sa valeur entre 2 appels) */ |
static int memo; |
} |
| 1|c|Initialisation des variables |
|---|
int globale=3; |
|
void hop() |
{ |
int locale=2; |
static int statique=4; |
complex z={1,2}; |
double tb[2]={3,4}; |
int A[]={2,4}; |
int B[][3]={{1,2,3},{4,5,6}}; |
complex C[]={{1,2},{3,4}}; |
} |
| 1|c|Passage par variable |
|---|
void max(double x,double y, |
double *z) |
{ |
if (x<y) |
*z=y; |
else |
*z=x; |
} |
... |
max(x,y,&z); |
... |
| 1|c|Conditions |
|---|
if (test ) { |
... |
} |
if (test ) { |
... |
} else { |
... |
} |
switch (i) { |
case 1: |
... |
break; |
case 2: |
... |
break; |
default: |
... |
} |
| 2|c|Tests | |
|---|---|
| égal | == |
| différent | != |
| supérieur | > et >= |
| inférieur | < et <= |
| et | && |
| ou | || |
| non | ! |
| 1|c|Boucles |
|---|
for (i=1;i<=n;i=i+1) { |
... |
} |
while (i<j) { |
... |
} |
do { |
... |
} while (i<j); |
| 1|c|Structures |
|---|
| typedef struct { |
| double a; |
| double b; |
| } complex; |
| complex z; |
| z.a=2; |
| z.b=3; |
| typedef struct list { |
| int val; |
| struct list *next; |
| } list; |
| 2|c|Contractions | |
|---|---|
| i=i+1; | i++; |
| (*c).a | c->a |
| &(*i) | i |
| 1|c|Maths |
|---|
| #include <math.h> |
| x=sqrt(y); |
| x=pow(y,3); |
LDLIBS=-lm |
| 1|c|Tableaux |
|---|
| /* un tableau est toujours |
| passé par variable */ |
| /* Passage de la dimension |
| inutile */ |
| 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++) |
printf("tb[%d]=%d\n", |
i,tb[i]); |
| ... |
| 1|c|Tableaux multidim |
|---|
| /* un tableau est toujours |
passé par variable */ |
| /* 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++) |
printf("tb[%d,%d]=%d\n", |
i,j,tb[i][j]); |
| ... |
| 1|c|Abréviations de type |
|---|
typedef enum {Nord, Est, Sud, Ouest} direction; |
typedef char[N] string; |
typedef double (*fun)(double); |
| 1|c|16. Tableaux taille variable |
|---|
#include <stdlib.h> |
|
void remplit(int t[],int n) |
{ |
... |
} |
|
int main() |
{ |
int *t; |
int n; |
|
scanf("%d",&n); |
t=malloc(n*sizeof(int)); |
remplit(t,n); |
... |
free(t); |
} |
#include <stdlib.h> |
|
... |
data *rep; |
|
... |
rep=malloc(n*sizeof(data)); |
... |
n=new_n; |
rep=realloc(rep,n*sizeof(data)); |
... |
free(rep); |
| 1|c|Entrées/Sorties |
|---|
#include <stdio.h> |
printf("%d %f %c %s\n",i,x,c,s); |
scanf("%d %lf %c %s",&i,&x,&c,s); |
program < data > out |
#include <stdio.h> |
|
... |
FILE *in,*out; |
|
in=fopen("data","r"); |
if (!in) { |
printf("erreur de lecture\n"); |
exit(1); |
} |
... |
fscanf(in,"%d %lf %c %s",&i,&x,&c,s);, |
... |
fclose(in); |
... |
out=fopen("out","w"); |
if (!out) { |
printf("erreur d'écriture\n"); |
exit(1); |
} |
... |
fprint(out,"Résultats: %d %lf\n",n,y);, |
... |
fclose(out); |
#include <stdlib.h> |
|
int main(int argc, char argv[]) |
{ |
char name[32]; |
int n; |
double x; |
|
if (argc != 4) { |
printf("Syntax: %s name n x\n",argv[0]); |
exit(1); |
} |
strcpy(name,argv[1]); |
n=atoi(argv[2]); |
x=atof(argv[3]); |
... |
} |
| 2|c|Arithmétique | |
|---|---|
| Modulo | j=i%n |
(attention -7%5 vaut -2) |
|
| Division réelle | x=(double)i/j; |
| x=i/2.0; |
| 1|c|Caractères |
|---|
| char c; |
scanf("%c",&c); |
| c='a'; |
printf("%c\n",c); |
| 1|c|Chaînes |
|---|
| char s[32]; |
scanf("%s",s); |
printf("%s\n",s); |
sprintf(s,"%d",i); |
| c=s[i]; |
| s[i]='a'; |
| #include <string.h> |
| l=strlen(s); |
| strcpy(dest,source); |
| strcmp(s1,s2); |
| 1|c|Makefile |
|---|
| LDLIBS=... |
| 2|c|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 |
| 2|c|Souris | |
|---|---|
| Recopier | |
| 1- Début | Clic gauche |
| 2- Fin | Clic droit |
| 3- Copier | Clic mileu |
| 2|c|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 |
| 1|c|Graphiques |
|---|
| #include <win.h> |
| 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(int millisec); |
| white,black,blue,red,green,yellow,cyan,magenta |
| LDLIBS=-lwin -lXm -lXt -lX11 |
| 3|c|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) <no ligne> | 10 lignes autour | |
| l(ist) <fonction> | ||
| Interrompre l'exécution | kill | abandonner l'exécution |
| b(reak) <no ligne> | 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 <no pt d'arrêt> | 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 <no ligne> | jusqu'à la ligne | |
| Naviguer dans la pile | up | monter d'un niveau |
| down | descendre d'un niveau | |
| fr(ame) <no niveau> | aller à un niveau donné | |
| bt (backtrace) | afficher la pile |
| 3|c|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 |
| 3|c|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 |
WIN v1.6
Bibliothèque Graphique de Base