Thierry Salset
On trouvera placés en vis à vis des exemples écrits en Pascal (colonne gauche) et en C (colonne droite) suivis d'un commentaire destiné à mettre en évidence les différences entre ces deux langages.
Programme principal | |
---|---|
(* programme principal *) program p(input,output); begin end. |
/* programme principal */ int main() { } |
Noter la différence de syntaxe des commentaires. |
Identificateurs | |
---|---|
unIdent z0 |
unIdent un_ident_C z0 |
Un identificateur en C doit commencer par une lettre ; ensuite on a droit aux lettres, aux chiffres et au caractère << souligné >>. La syntaxe du C distingue les lettres majuscules des lettres minuscules. |
Déclarations | |
---|---|
const N = 100; type Tab = array[1..N,1..N] of integer; var a: Tab; i: integer; procedure init(n: integer); function pred(i: integer): integer; |
#define N 100 int i; void init(int n); typedef int Tab[N][N]; Tab a; int pred(int i); |
En C, il n'y a pas d'ordre précis dans les déclarations si ce n'est que la déclaration d'un nom doit toujours précéder son utilisation. La définition des constantes utilise les capacités du pré-processeur. |
Point-virgule et instructions | |
---|---|
begin p := p - 1; a := x * a end |
{ p = p - 1; a = x * a; } |
En C, Une intruction simple se termine par un point-virgule. Il fait partie de l'instruction alors qu'en Pascal, il est un séparateur d'instructions. En C, il n'y a jamais de point-virgule derrière une accolade fermant un bloc d'instructions. |
Quelques opérateurs | |
---|---|
(* égalité *) s = 0 (* inégalité *) s <> 0 (* ET logique *) a and b (* OU logique *) a or b (* négation logique *) not a |
s == 0 s != 0 a && b a || b !a |
Noter la différence de syntaxe, en particulier celle du test d'égalité. |
Instructions non itératives | |
---|---|
(* affectation *) x := 1 (* conditionnelle *) if a > b then z := a else z := b (* sélection *) case c of 'a','b' : writeln('bonjour'); 'z' : writeln('au revoir'); otherwise writeln('goujat') end |
x = 1; if (a > b) z = a; else z = b; switch(c) { case 'a' : case 'b' : printf("bonjour\n"); break; case 'z' : printf("au revoir\n"); break; default : printf("goujat\n"); } |
Remarquer l'instruction break dans le switch en C, elle fait sortir du switch. En l'absence de break, les clauses du switch sont exécutées en séquence jusqu'à la fin. |
Instructions itératives | |
---|---|
while y > 0 do begin t := x mod y; x := y; y := t end repeat j := j-1 until a[j] <= v for i := 0 to N-1 do begin a[i] = 0 end for i := N-1 downto 0 do begin a[i] = 0 end |
while (y > 0) { t = x%y; x = y; y = t; } do { j = j-1 } while (a[j] > v) for (i=0; i < N; i++) { a[i] = 0; } for (i=N-1; i >= 0; i--) { a[i] = 0; } |
Noter que l'instruction Pascal repeat S1;...;Sn
until b exécute S1;...;Sn tant que l'expression
booléenne est fausse alors que le do S
while b de C exécute S tant que
l'expression booléenne b est vraie. L'instruction for du Pascal permet d'avoir un incrément de 1 ou -1 seulement ; le for du C est beaucoup plus général. |
Typage | |
---|---|
var b: boolean; x: 1..99; |
int b,x; double a; int gros = INT_MAX; /* coercition */ a = (double)gros+1; |
C est un langage typé, toutefois il est possible de convertir une
valeur d'un type en une valeur d'un autre type. On appelle ça une
coercition. Le type de base boolean n'existe pas en C. C'est la valeur numérique entière 0 qui représente le faux et n'importe quelle valeur numérique entière différente de 0, le vrai. Il n'y pas de type << intervalle >> et pas de type << ensemble >> en C. |
Tableaux | |
---|---|
var v: array [1..100][1..2] of real; |
double v[100][2]; |
En C, l'indice d'un tableau de taille N varie obligatoirement de 0 à N-1. La notation A[i,j] autorisée en Pascal si A est un tableau bidimensionnel n'est pas acceptée en C ; il faut écrire A[i][j]. |
Fonctions et Procédures | |
---|---|
var k: integer; procedure raz; begin k := 0 end; function dist(x,y: real): real begin dist := sqrt(x*x + y*y) end; |
int k; void raz() { k = 0; } double dist(double x, double y) { return sqrt(x*x + y*y); } |
En Pascal, le nom d'une fonction sans argument n'est pas suivi de
().
La valeur de retour d'une fonction est transmise à l'appelant par une affectation spéciale à une variable ayant le nom de la fonction. En C, c'est par l'instruction return. Il n'y pas d'objet de type procédure en C. Ce sont simplement des fonctions retournant void. C n'offre pas la possibilité de définir des fonctions à l'intérieur d'une autre fonction. |
Adresses | |
---|---|
int i, *ptr; ptr = &i; |
|
En C, il est possible de manipuler explicitement les adresses mémoire. On peut les stocker dans des variables de type pointeurs. |
Pointeurs | |
---|---|
var pa: ^integer; b: integer; b := 7; new(pa); pa^ := b; dispose(pa) |
int *pa,b=7; pa = malloc(sizeof(int)); *pa = b; free(pa); |
En Pascal, un pointeur désigne nécessairement un objet dynamique.
Les pointeurs du langage C n'ont pas cette limitation, ils peuvent
mémoriser l'adresse d'un objet quelconque.
L'équivalent C du couple d'instructions Pascal new/dispose est le couple de fonctions de la bibliothèque C standard malloc/free. Le pointeur nul qui est égal à la valeur de nil en Pascal, est égal à la valeur de la constante NULL en C. |
Passage d'arguments | |
---|---|
var a,b: integer; procedure swap(var x,y : integer); var z: integer; begin z:=x; x:=y; y:=z end; begin swap(a,b); end. |
void swap(int *px, int *py) { int z=*px; *px=*py; *py=z; } main () { int a,b; swap(&a,&b); } |
En Pascal, les arguments peuvent être passés par valeur ou par
variable (référence).
C n'a qu'un seul mode de passage d'argument, par valeur. Pour obtenir un passage par variable (par adresse), il faut passer explicitement l'adresse de la variable. |
Structures | |
---|---|
type complex = record re: real; im: real end; var z: complex; begin z.re := 1.0; z.im := -1.0 end (* ou bien *) with z do begin re := 1.0; im := -1.0 end |
typedef struct complex { double re; double im; } complex; complex z = {0, 0}; { z.re = 1; z.im = -1; } |
L'analogue C d'un enregistrement Pascal est la << structure >>
introduite par le mot-clé struct. Une structure C ne peut
pas avoir de << variantes >>.
L'instruction with n'existe pas en C. |
Un exemple complet : les listes chaînées | |
---|---|
program list(); type List = ^Cell; Cell = record val: integer; next: List end; var l: List; i: integer; function cons(n: integer; l: List) : List var c: List; begin new(c); c^.val := n; c^.next := l; cons:=c end; procedure freeList(l: List); if l <> nil then begin freeList(l^.next); dispose(l) end; begin l:= nil; for i:=1 to 100 do l := cons(i*i,l); ... freeList(l) end. |
typedef struct cell { int val; struct cell *next; } List; List *cons(int n, List *l) { List *c = malloc(sizeof(List)); c->val = n; c->next = l; return c; } void freeList(List *l) { if (l) { freeList(l->next); free(l); } } main () { List *l = NULL; int i; for(i=1;i<=100;i++) { l = cons(i*i,l); } ... freeList(l); } |
Entrées/sorties | |
---|---|
var x: real; y: integer; readln(x,y) writeln(x,y) |
#include |
C ne possède pas d'\emph{instructions} d'entrées/sorties, il faut utiliser des \emph{fonctions} définies dans la bibliothèque standard (noter l'inclusion du fichier d'en-têtes stdio.h). À la place des instructions Pascal write et writeln, utiliser en C la fonction d'impression formatée printf. De même, à la place de read et readln, utiliser scanf. Remarquer le \n inséré à la fin du format du printf pour faire un saut de ligne alors qu'il est implicitement réalisé par la fonction writeln |
Fichiers | |
---|---|
program copier; var in,out: file of char; c: char; begin reset(in,'foo'); rewrite(out,'bar'); while not eof(in) do begin read(in,c); write(out,c) end; close(in); close(out) end. |
#include |
Le langage Pascal définit sa propre notion de fichier alors que C
se repose sur celle du système et ne propose rien de plus. Un
fichier est simplement une suite de caractères ; il n'a donc pas de
structure particulière. Pour Pascal, un fichier est une suite
d'objets d'un certain type.
La fonction fopen associe à un fichier réel un objet de type FILE. L'association est rompue par fclose. Si la fin d'un fichier est atteinte, la fonction d'entrée getc retourne la valeur de la constante EOF. Les fonctions d'entrées/sorties formatées qui opèrent sur des fichiers s'appellent fscanf et fprintf. Elles s'emploient comme scanf et printf sauf qu'elles prennent un pointeur sur un objet de type FILE en premier argument. |