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.  | 
  |