C / C++ int[] vs int* (notation pointeurs vs. tableau). Quelle est la différence?

je sais que les tableaux en C ne sont que des pointeurs vers des données stockées de façon séquentielle. Mais quelles différences impliquent la différence dans la notation [] et *. Je veux dire dans tous les contextes d'utilisation possibles. Par exemple:

char c[] = "test";

si vous fournissez cette instruction dans un corps de fonction il attribuera la chaîne sur une pile tandis que

char* c = "test";

pointera vers un segment data (readonly).

Pouvez-vous énumérer toutes les différences entre ces deux notations dans TOUS les contextes d'utilisation d'un formulaire claire vue générale.

31
demandé sur Sergey K. 2012-07-19 11:35:58

5 réponses

selon la norme C99:

un type de tableau décrit un ensemble non vide attribué de façon contiguë les objets avec un type d'objet, appelé l'élément type.36) les types de réseaux sont caractérisés par leur type d'élément et par le nombre d'éléments dans le tableau. Un type tableau est dit dérivé de son type d'élément, et si son type d'élément est T, le tableau le type est parfois appelé "tableau de T". La construction d'un tableau type à partir d'un le type d'élément est appelé "dérivation du type de tableau".


Un pointeur de type peut être dérivé d'un type de fonction, un type d'objet, ou un type incomplet, appelé type référencé. Un type de pointeur décrit un objet dont la valeur fournit une référence à une entité de le type de référence. Un type de pointeur dérivé du type de référence T est parfois appelé ‘pointer vers T". La construction d'un pointeur le type d'un type référencé est appelé ‘pointeur de dérivation de type’.

selon les déclarations standard

char s[] = "abc", t[3] = "abc";
char s[] = { 'a', 'b', 'c', '' }, t[] = { 'a', 'b', 'c' };

sont identiques. Le contenu des tableaux est modifiable. D'autre part, la déclaration const char *p = "abc"; définit p avec le type "pointeur vers char constant ‘et l'initialise pour pointer vers un objet avec le type’ tableau constant de char" (en C++) avec la longueur 4 dont les éléments sont initialisés avec une chaîne de caractères littérale. Si l'on tente d'utiliser p pour modifier le contenu du tableau, le comportement est indéfini.

Selon 6.3.2.1 Array subscripting référence et des indices de tableaux sont identiques:

la définition de l'opérateur en indice [] est que E1[E2] est identique à (*((E1)+(E2)).

les différences entre les tableaux et les pointeurs sont:

  • pointeur n'a pas d'information de la taille de la mémoire derrière elle (il n'y a aucun moyen portable pour l'obtenir)
  • un tableau de type incomplet ne peut pas être construit
  • un type de pointeur peut être dérivé d'un type incomplet
  • un pointeur peut définir une structure récursive (c'est la conséquence des deux précédents)

ces liens peuvent être utiles au sujet:

21
répondu Sergey K. 2012-07-19 15:26:02
char c[] = "test";

cela va créer un tableau contenant le test string de sorte que vous pouvez modifier/changer n'importe quel caractère, dire

c[2] = 'p';

mais

char * c = "test"

C'est une chaîne littérale, c'est un const char.

Donc toute modification à cette chaîne littérale nous donne segfault. Donc

c[2] = 'p';

est illégal maintenant et nous donne segfault.

8
répondu neel 2012-07-19 08:33:54

char [] indique le type "tableau d'inconnu lié de char", tandis que char * indique le type "pointer vers char". Comme vous l'avez observé, lors de la définition d'une variable de type "tableau de l'inconnu lié de char" est initialisé avec une chaîne littérale, le type est converti en "tableau[N] de char", où N est la taille appropriée. La même chose s'applique en général à l'initialisation à partir du tableau aggregate:

int arr[] = { 0, 1, 2 };

arr est converti en type "array[3] de l'int".

Dans un définition de type définie par l'utilisateur (struct,class ou union), les types liés à un array-of-unknown-bound sont interdits en C++, bien que dans certaines versions de C ils soient autorisés comme dernière membre d'une structure, où ils peuvent être utilisés pour accéder à la mémoire allouée après la fin de la structure; cette utilisation est appelé "lanternes".

la construction de type récursif est une autre différence; on peut construire des pointeurs et des tableaux de char *(e.g. char **,char (*)[10]) mais c'est illégal pour les tableaux des inconnus liés; on ne peut pas écrire char []* ou char [][10] (bien que char (*)[] et char [10][] sont très bien).

enfin, la qualification cv fonctionne différemment; étant donné typedef char *ptr_to_char et typedef char array_of_unknown_bound_of_char[], cv-qualifier la version pointeur se comportera comme prévu, tandis que cv-qualifier la version Tableau migrera la CV-qualification vers le type d'élément: c'est-à-dire,const array_of_unknown_bound_of_char est équivalent à const char [] et pas de la fiction char (const) []. Cela signifie que dans une définition de fonction, où array-to-point decay opère sur les arguments avant de construire le prototype,

void foo (int const a[]) {
    a = 0;
}

est légal; il n'y a aucun moyen de rendre le paramètre lié au tableau-of-unknown-bound non modifiable.

3
répondu ecatmur 2012-07-19 08:20:28

Le tout devient clair si vous savez que déclarer une variable de pointeur ne crée pas le type de variable, il pointe à. Il crée une variable de pointeur.

Donc, dans la pratique, si vous avez besoin d'une chaîne de caractères, alors vous devez spécifier un tableau de caractères et un pointeur peut être utilisé plus tard.

1
répondu Shash 2018-08-06 06:12:43

en fait les tableaux sont équivalents à constante des pointeurs.

aussi, char c [] alloue de la mémoire pour le tableau, dont l'adresse de base est c lui-même. Aucune mémoire séparée n'est attribuée pour stocker cette adresse.

écriture char *C alloue de la mémoire pour la chaîne dont l'adresse de base est stockée dans C. En outre, un emplacement de mémoire séparé est utilisé pour stocker C.

0
répondu Cygnus 2012-07-19 08:11:47