502 votes

Quelle est la différence entre char s [] et char * s en C ?

En C, je peux faire comme ceci:

 char s[]="hello";
 

ou

 char *s ="hello";
 

Alors je me demande quelle est la différence? Je veux savoir ce qui se passe réellement dans l'allocation de mémoire pendant la compilation et l'exécution.

538voto

Rickard Points 2411

La différence ici est que

 char *s = "Hello world";
 

placera Hello world dans les parties en lecture seule de la mémoire et en faisant pointeur sa, rendant toute opération d'écriture sur cette mémoire illégale. Tout en faisant:

 char s[] = "Hello world";
 

place la chaîne littérale dans la mémoire morte et copie la chaîne dans la nouvelle mémoire allouée sur la pile. Ainsi faisant

 s[0] = 'J';
 

légal.

151voto

bdonlan Points 90068

Tout d'abord, dans les arguments de la fonction, ils sont exactement équivalentes:

void foo(char *x);
void foo(char x[]); // exactly the same in all respects (note! this only applies if the brackets are empty)

Dans d'autres contextes, char * alloue un pointeur, alors que char [] alloue un tableau. D'où vient la chaîne d'aller dans le premier cas, vous demandez-vous? Le compilateur secrètement alloue un statique anonyme tableau pour contenir la chaîne de caractères littérale. Donc:

char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;

Notez que vous ne devez jamais tenter de modifier le contenu de ce tableau anonyme par le biais de ce pointeur; les effets ne sont pas définis (souvent le sens d'un crash):

x[1] = 'O'; // BAD. DON'T DO THIS.

À l'aide de la syntaxe de tableau attribue directement à la mémoire. Ainsi, la modification est sûr:

char x[] = "Foo";
x[1] = 'O'; // No problem.

Toutefois, le tableau ne vit que tant que son contenant de la portée, de sorte que si vous le faites dans une fonction ne retourne pas de fuite ou un pointeur vers ce tableau - faire une copie plutôt qu'avec des strdup() ou similaire. Si le tableau est alloué dans la portée globale, bien sûr, pas de problème.

71voto

caf Points 114951

La présente déclaration:

char s[] = "hello";

Crée un objet - char tableau de taille 6 s, initialisé avec les valeurs 'h', 'e', 'l', 'l', 'o', '\0'. D'où ce tableau est alloué dans la mémoire, et la durée de vie, dépend de l'endroit où la déclaration apparaît. Si la déclaration est à l'intérieur d'une fonction, il va vivre jusqu'à la fin du bloc qu'elle est déclarée, et presque certainement être allouée sur la pile; si c'est en dehors d'une fonction, il va probablement être stockés à l'intérieur d'un "initialisation de segment de données" qui est chargé à partir du fichier exécutable en écriture de la mémoire lorsque le programme est exécuté.

D'autre part, cette déclaration:

char *s ="hello";

Crée deux objets:

  • une lecture seule matrice de 6 chars contenant les valeurs 'h', 'e', 'l', 'l', 'o', '\0', ce qui n'a pas de nom et est statique de la durée de stockage (ce qui signifie qu'il vit pour l'ensemble de la durée de vie du programme); et
  • une variable de type pointeur vers char, appelés s, ce qui est initialisé avec l'emplacement du premier caractère que sans nom, en lecture seule matrice.

Sans nom en lecture seule matrice est généralement situé dans le "texte" segment du programme, ce qui signifie qu'il est chargé à partir du disque dans la mémoire en lecture seule, avec le code en lui-même. L'emplacement de l' s pointeur de la variable dans la mémoire dépend de l'endroit où la déclaration apparaît (comme dans le premier exemple).

59voto

John Bode Points 33046

Étant donné les déclarations

char *s0 = "hello world";
char s1[] = "hello world";

supposons que celui-ci hypothétique de la mémoire de la carte:

 0x01 0x02 0x03 0x04
 0x00008000: 'h', 'e', 'l', 'l'
 0x00008004: 'o' '' 'w' 'o'
 0x00008008: 'r' 'l' 'd' 0x00
...
s0: 0x00010000: 0x00 0x00 0x80, 0x00
s1: 0x00010004: 'h', 'e', 'l', 'l'
 0x00010008: 'o' '' 'w' 'o'
 0x0001000C: 'r' 'l' 'd' 0x00

Le littéral de chaîne "hello world" est un 12-élément de tableau de char (const char en C++) avec statique de la mesure, ce qui signifie que la mémoire est allouée lorsque le programme démarre et reste affecté jusqu'à ce que la mémoire se termine. Tenter de modifier le contenu d'une chaîne de caractères littérale invoque un comportement indéfini.

La ligne

char *s0 = "hello world";

définit s0 comme un pointeur vers char avec l'auto-mesure (ce qui signifie que la variable s0 n'existe que pour le champ dans lequel elle est déclarée) et copie l' adresse de la chaîne littérale (0x00008000 dans cet exemple). A noter que depuis s0 de points à un littéral de chaîne, il ne devrait pas être utilisée comme argument d'une fonction qui permettrait d'essayer de la modifier (par exemple, strtok(), strcat(), strcpy(), etc.).

La ligne

char s1[] = "hello world";

définit s1 12 élément de tableau de char (la longueur est prise à partir de la chaîne littérale) avec auto mesure et copie le contenu de la lettre au tableau. Comme vous pouvez le voir à partir de la carte mémoire, nous avons deux copies de la chaîne "hello world"; la différence est que vous pouvez modifier la chaîne contenue dans s1.

s0 et s1 sont interchangeables dans la plupart des contextes, voici les exceptions:

sizeof s0 == sizeof (char*)
sizeof s1 == 12

type of &s0 == char **
type of &s1 == char (*)[12] // pointer to a 12-element array of char

Vous pouvez réattribuer la variable s0 à point à un autre littéral de chaîne ou d'une autre variable. Vous ne pouvez pas réaffecter la variable s1 à point à un autre tableau.

15voto

Charles Bailey Points 244082

.

char s[] = "hello";

déclare s être un tableau d' char ce qui est assez long pour contenir l'initialiseur (5 + 1 chars) et initialise le tableau en copiant les membres de la chaîne littérale dans le tableau.

char *s = "hello";

déclare s être un pointeur sur un ou plusieurs (dans ce cas plus) chars et des points directement à un fixe (en lecture seule) l'emplacement contenant le littéral "hello".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X