FAQ CConsultez toutes les FAQ

Nombre d'auteurs : 27, nombre de questions : 175, dernière mise à jour : 17 décembre 2010  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de www.developpez.com et de l'expérience personnelle des auteurs.

Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci .

Sur ce, je vous souhaite une bonne lecture.


SommairePointeurs, tableaux et chaînes de caractèresLes tableaux (10)
précédent sommaire suivant
 

int t[] = {10, 20}; crée un tableau de deux éléments initialisé avec les valeurs t[0] = 10 et t[1] = 20. Cette écriture est donc strictement équivalente à : int t[2] = {10, 20};.

Mis à jour le 23 mars 2009 Melem

int t[10] = {10, 20}; crée un tableau de 10 éléments initialisé avec les valeurs t[0] = 10, t[1] = 20 et t[2] à t[9] à 0. Notez bien que la mise à 0 des éléments non initialisés d'une variable locale tableau n'a lieu que lorsqu'un élément au moins a été initialisé.

Mis à jour le 23 mars 2009 Melem

t représente l'objet tableau, &t l'adresse de ce tableau et &(t[0]) l'adresse du premier élément du tableau. Ces trois expressions sont donc très différentes et n'ont à priori aucun point commun. Toutefois, &t et &(t[0]) représentent la même adresse, même si elles n'ont pas le même type (pour rappel, les adresses sont typées en C). t tout court quant à lui, lorsqu'il n'est pas utilisé dans sizeof ou avec l'opérateur & (« adresse de »), est toujours converti par le compilateur en &(t[0]). D'autres conversions de ce genre existent également (avec plus ou moins de conditions pour avoir lieu) et elles sont nombreuses. Ce sont ce qu'on appelle les conversions implicites.

La chose la plus importante à retenir est donc qu'une expression de type tableau (comme notre t ci-dessus, qui est de type int [10]), sauf lorsqu'elle est utilisée en unique argument de sizeof ou de l'opérateur & (« adresse de »), est toujours convertie par le compilateur en un pointeur vers son premier élément. Sinon il est reste un tableau.

Mis à jour le 2 mars 2003 Bob Melem

Pour comprendre le sens de cette expression, il faut au moins savoir deux choses :

  • Les adresses sont typées en C. Ajouter 1 à un pointeur revient à se déplacer en mémoire de la taille de la donnée pointée et non de 1 byte.
  • Le nom d'un tableau (t), sauf lorsqu'il apparaît dans un sizeof ou à droite de l'opérateur & (« adresse de »), représente toujours un pointeur vers son premier élément (c'est-à-dire &(t[0])).

Le petit programme suivant devrait rendre les choses plus claires.

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h> 
  
int main(void) 
{ 
    int t[] = {10, 20, 30, 40}; 
    int * p = t; 
  
    /* p pointe sur t[0] donc *p équivaut à t[0].                                   */ 
  
    printf("t[0] = %d\n", *p); 
  
    /* p pointe sur t[0] donc p + 1 pointe sur t[1]. *(p + 1) équivaut donc à t[1]. */ 
  
    printf("t[1] = %d\n", *(p + 1)); 
  
    /* p pointe sur t[0] donc p + 2 pointe sur t[2]. *(p + 2) équivaut donc à t[2]. */ 
  
    printf("t[2] = %d\n", *(p + 2)); 
  
    /* p pointe sur t[0] donc p + 3 pointe sur t[3]. *(p + 3) équivaut donc à t[3]. */ 
  
    printf("t[3] = %d\n", *(p + 3)); 
  
    return 0; 
}
Ou, sans l'aide de la variable p :

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h> 
  
int main(void) 
{ 
    int t[] = {10, 20, 30, 40}; 
  
    printf("t[0] = %d\n", *t); 
    printf("t[1] = %d\n", *(t + 1)); 
    printf("t[2] = %d\n", *(t + 2)); 
    printf("t[3] = %d\n", *(t + 3)); 
  
    return 0; 
}

Mis à jour le 7 novembre 2005 gege2061

Cet opérateur permet d'accéder à un élément d'un tableau. Il requiert deux opérandes : une de type pointeur et l'autre de type entier. L'expression X[Y] est équivalente à *((X) + (Y)). Autrement dit, si p possède un type pointeur, alors les expressions p[1], 1[p] et *(p + 1) sont strictement équivalentes, tout comme p[-1], (-1)[p] et *(p - 1), etc.

Mis à jour le 27 juillet 2008 gege2061 Melem

Soit t un tableau. Que signifie *(t + 3) ?

En langage C, on ne classe pas les tableaux selon leurs dimensions, un tableau « à plusieurs dimensions » n'est d'ailleurs en C qu'un tableau dont les éléments sont eux aussi des tableaux. Il n'y a donc pas des règles spéciales pour ces tableaux « à plusieurs dimensions ». Voici un exemple de programme manipulant un tableau dont les éléments sont des tableaux.

Code c :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h> 
  
int main(void) 
{ 
    int t[10][4]; /* t est un tableau de 10 éléments ou */ 
    /* chaque élément est un tableau de 4 entiers       */ 
  
    size_t j, i; 
  
    /* Parcourons les éléments du tableau (t[0] a t[9]) */ 
    for(j = 0; j < sizeof(t) / sizeof(t[0]); j++) 
    { 
        /* Pour chaque élément t[j] du tableau, initialisons */ 
        /* les éléments de t[j] (t[j][0] a t[j][3])          */ 
  
        for(i = 0; i < sizeof(t[j]) / sizeof(t[j][0]); i++) 
        { 
            t[j][i] = j; 
  
            /* Puis affichons t[j][i] */ 
  
            printf("%d\t", t[j][i]); 
        } 
  
        printf("\n"); 
    } 
  
    return 0; 
}

Mis à jour le 23 mars 2009 Melem

int (*p)[4]; crée une variable p tel que (*p) est un tableau de 4 entiers. p est donc un pointeur vers un tableau de 4 entiers. Il est de type int (*)[4]. On ne peut pas utiliser un tel nom de type pour déclarer une variable par exemple mais on peut par contre l'utiliser dans un cast ou un sizeof. Le programme suivant donne un exemple d'utilisation d'un pointeur vers tableau.

Code c :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h> 
  
int main(void) 
{ 
    int t[10][4]; 
    int (*p)[4] = t; /* p pointe sur t[0]. *p <=> t[0]. */; 
  
    ( *p )[0] = 0; /* t[0][0] = 0 */ 
    ( *p )[1] = 0; /* t[0][1] = 1 */ 
  
    ( *(p + 1) )[0] = 1; /* t[1][0] = 1 */ 
    ( *(p + 1) )[1] = 1; /* t[1][1] = 1 */ 
  
    printf("t[0][0] = %d\n", t[0][0]); 
    printf("t[0][1] = %d\n", t[0][1]); 
    printf("t[1][0] = %d\n", t[1][0]); 
    printf("t[1][1] = %d\n", t[1][1]); 
  
    return 0; 
}

Mis à jour le 23 mars 2009 Melem

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h> 
  
/* Définition d'un type fonction */ 
  
typedef int F(void); 
  
/* Voici deux fonctions de type F */ 
  
int f1(void); 
int f2(void); 
  
/* Maintenant la fonction principale */ 
  
int main(void) 
{ 
    F * t[2]; 
  
    t[0] = f1; 
    t[1] = f2; 
  
    printf("t[0]() = %d\n", t[0]()); 
    printf("t[1]() = %d\n", t[1]()); 
  
    return 0; 
} 
  
int f1(void) 
{ 
    return 1; 
} 
  
int f2(void) 
{ 
    return 2; 
}
Étant donné que les fonctions, à l'instar des variables permanentes, existent en mémoire pendant toute l'exécution du programme, l'adresse d'une fonction peut être utilisée pour initialiser une variable permanente (en termes techniques, l'adresse d'une fonction, tout comme l'adresse d'une variable permanente, est donc, en C, une « expression constante »).

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h> 
  
typedef int F(void); 
  
int f1(void); 
int f2(void); 
  
F * t[] = {f1, f2}; 
  
int main(void) 
{ 
    printf("t[0]() = %d\n", t[0]()); 
    printf("t[1]() = %d\n", t[1]()); 
  
    return 0; 
} 
  
int f1(void) 
{ 
    return 1; 
} 
  
int f2(void) 
{ 
    return 2; 
}

Mis à jour le 15 mai 2003 joellel Melem

Lorsqu'un tableau figure en paramètre d'une fonction, il est automatiquement converti en son adresse (plus précisément en l'adresse de son premier élément). Un tableau n'est donc jamais copié par une fonction. La méthode généralement utilisée pour passer un tableau à une fonction c'est de passer un pointeur vers son premier élément et sa taille (si nécessaire) comme paramètres.

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h> 
  
void initialiser_tab(int * ptr, size_t n_elements) 
{ 
    size_t i; 
  
    for(i = 0; i < n_elements; i++) 
        ptr[i] = (int)i; 
} 
  
int main(void) 
{ 
    int t[10]; 
    size_t i, n_elements = sizeof(t) / sizeof(t[0]); 
  
    /* t peut egalement s'ecrire &(t[0]) */ 
    initialiser_tab(t, n_elements); 
  
    for(i = 0; i < n_elements; i++) 
        printf("%d\n", t[i]); 
  
    return 0; 
}
Étant donné qu'un tableau est toujours converti en un pointeur vers son premier élément, les prototypes suivants sont strictement les mêmes :

Code C :
1
2
3
void initialiser_tab(int * ptr, size_t n_elements) 
void initialiser_tab(int ptr[], size_t n_elements) 
void initialiser_tab(int ptr[10], size_t n_elements) /* Le 10 ne sert absolument à rien */
Voici un exemple avec un tableau « à deux dimensions » :

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h> 
  
/* initialiser_tab_2 : initialise un tableau de N éléments ou */ 
/* chaque élément est un tableau de M entiers .               */ 
  
void initialiser_tab_2(int * ptr, size_t N, size_t M) 
{     
    /* ptr = &(t[0][0]) d'ou :      */ 
    /* - ptr[i] <=> t[0][i]         */ 
    /* - ptr[M * j] <=> t[j][0]     */ 
    /* - ptr[M * j + i] <=> t[j][i] */ 
  
    size_t j, i; 
  
    for(j = 0; j < N; j++) 
    { 
        for(i = 0; i < M; i++) 
        { 
            ptr[M * j + i] = (int)j; 
        } 
    } 
} 
  
int main(void) 
{ 
    int t[10][4]; 
    size_t j, i; 
    size_t N = sizeof(t) / sizeof(t[0]), M = sizeof(t[0]) / sizeof(t[0][0]); 
  
    /* &(t[0][0]) peut également s'écrire t[0] ou encore (int *)t */ 
    initialiser_tab_2(&(t[0][0]), N, M); 
  
    for(j = 0; j < N; j++) 
    { 
        for(i = 0; i < M; i++) 
            printf("%d\t", t[j][i]); 
  
        printf("\n"); 
    } 
  
    return 0; 
}

Mis à jour le 29 janvier 2003 Bob gl Melem

Pour copier un tableau, on a deux solutions. La première consiste à copier chaque case du tableau numéro 1 dans la case correspondante du tableau numéro 2. Mais cette manière est parfois complexe et risque d'être lente.

La deuxième possibilité est d'utiliser la fonction memcpy(). Elle admet trois paramètres, le premier étant le tableau de destination et le deuxième le tableau source. Enfin, le troisième est le nombre d'octets à copier. Par exemple, pour copier le tableau Tab1 dans le tableau Tab2, il suffit de faire :

Code C :
1
2
3
4
5
#include <string.h> 
  
int Tab1[10], Tab2[10]; 
  
memcpy(Tab2, Tab1, sizeof Tab2);

Mis à jour le 29 janvier 2003 Bob Emmanuel Delahaye

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
 
 
 
Partenaires

PlanetHoster
Ikoula