De l'Ada au C

De Ensiwiki
Aller à : navigation, rechercher

Cette page a pour but de vous éviter de tomber dans certains pièges en transposant vos habitudes Ada au C.

N'hésitez pas à rajouter des choses, et si vous n'êtes pas trop sûr, ou avez une suggestion mais ne savez pas comment le faire en C, discutez-en (lien « discussion », dans la barre du haut).

Tableaux et chaînes de caractères

Tableaux sur la pile

En Ada, vous pouvez faire ça :

procedure F(N: Natural) is
   V: string(N);
begin
   ...
end;

C'est un tableau de taille variable acquise par un paramètre en entrée. Ces tableaux n'existent pas en ANSI-C89 (celui que l'on vous apprend), les tableaux déclarés T v[N] sont de taille constante, et N doit être une constante, même pas une variable constante déclarée const int N = 42; par exemple ; pour donner un nom à N, utilisez #define ou enum :

#define N 42
/* ou */
enum { N = 42 };

Pour allouer un tableau dont la taille n'est connue que dynamiquement, passez par le tas (et n'oubliez pas de libérer la mémoire après) :

T *v;
...
v = malloc(sizeof *v * n);

Parcours d'une chaîne

Prenez le code Ada (on ferait plutôt S'Range, mais la transposition avec S'Length est plus visible) :

for I in 1..S'Length loop
   ...
end loop;

Pour faire la même chose en C (parcourir une chaîne de caractères), on serait tenté d'écrire :

for (i = 0; i < strlen(s); ++i) {
        ...
}

Mais la solution est en fait, si on reste avec des indices :

for (i = 0; s[i] != '\0'; ++i) {
        ...
}

Rappelez-vous, les chaînes terminent par '\0'.

La première façon n'est pas acceptable car vous révaluez strlen() à chaque passage dans la condition :

  • la chaîne pourrait avoir changé ;
  • sinon, vous recalculez inutilement la taille à chaque fois, c'est un appel de fonction de plus, et votre algo passe de O(n) à O(n^2) parce que strlen() est en O(n).

Taille de tableau

Il n'y a pas d'équivalent à 'Length en C, pour les tableaux en général. Gardez en tête que le C ne garde nulle part la taille d'un tableau et qu'il est de votre responsabilité de la passer aux routines qui en ont besoin. Typiquement, le code suivant :

type A is array (Integer range <>) of T;
...
procedure F(V: A);

devient en C :

void f(T v[], size_t n);

Tableaux comme valeurs

Les tableaux comme valeurs, aussi, il faut oublier : en C, vous ne pouvez pas renvoyer de tableau d'une fonction (enfin, pas directement), et de toute manière, vu que la taille devrait être constante, cela n'aurait aucun intérêt. De même, n'oubliez pas que tous les tableaux passés (directement) en entrée sont des pointeurs.

Typiquement :

type A is array (Integer range <>) of T;
...
function F(V: A) return A;

devient :

void f(T v[], size_t n);    /* vous modifiez directement le tableau */

Aussi, de manière liée, l'opérateur Ada permettant de prendre un sous-tableau n'est pas disponible en C, mais par manipulation intelligente des pointeurs, on arrive souvent au même résultat ; le sous-tableau de v d'indice (i..j) n'est autre que le tableau qui débute à l'adresse v+i de longueur j+1-i.