différence entre char * et char avec strcpy ()

J’ai eu des problèmes au cours des dernières heures sur un problème que je croyais comprendre. Voici mon problème:

void cut_str(char* entry, int offset) { strcpy(entry, entry + offset); } char works[128] = "example1\0"; char* doesnt = "example2\0"; printf("output:\n"); cut_str(works, 2); printf("%s\n", works); cut_str(doesnt, 2); printf("%s\n", doesnt); // output: // ample1 // Segmentation: fault 

J’ai l’impression qu’il y a quelque chose d’important dans char * / char [] que je ne vais pas arriver ici.

La différence réside dans le fait que ne pointe doesnt vers la mémoire qui appartient à une constante de chaîne et n’est donc pas accessible en écriture.

Quand tu fais ça

 char works[128] = "example1\0"; 

le compilateur copie le contenu d’une chaîne non inscriptible dans un tableau inscriptible. \0 n’est pas obligatoire, d’ailleurs.

Quand vous faites cela, cependant,

 char* doesnt = "example2\0"; 

le compilateur laisse le pointeur pointant vers une région de mémoire non inscriptible. De nouveau, \0 sera inséré par le compilateur.

Si vous utilisez gcc , vous pouvez l’avoir prévenu de l’initialisation de char * écriture avec des littéraux de chaîne. L’option est -Wwrite-ssortingngs . Vous recevrez un avertissement qui ressemble à ceci:

  warning: initialization discards qualifiers from pointer target type 

La bonne façon de déclarer votre pointeur ne est pas comme suit:

 const char* doesnt = "example2\0"; 

Les types char[] et char * sont assez similaires, vous avez donc raison. La différence réside dans ce qui se passe lorsque les objects des types sont initialisés. Votre object works , de type char[] , dispose de 128 octets de mémoire de stockage alloués sur la stack. Votre object, de type char * , n’a pas de stockage sur la stack.

La norme C ne spécifie pas exactement où la chaîne de données ne doit pas être stockée, mais il est fort probable qu’elle soit stockée dans un segment de données non modifiable chargé lorsque votre programme est chargé pour exécution. Ce n’est pas un stockage variable. Ainsi, le segfault lorsque vous essayez de le varier.

Cela alloue 128 octets sur la stack et utilise le nom de works pour faire référence à son adresse:

 char works[128]; 

Donc, works est un pointeur sur la mémoire inscriptible.

Cela crée un littéral de chaîne, qui est dans la mémoire en lecture seule, et utilise le doesnt pour faire référence à son adresse:

 char * doesnt = "example2\0"; 

Vous pouvez écrire des données dans des works , car ils pointent vers une mémoire inscriptible. Vous ne pouvez pas écrire de données dans doesnt , car elles pointent vers la mémoire en lecture seule.

Notez également qu’il n’est pas nécessaire de terminer vos littéraux de chaîne par "\0" , car tous les littéraux de chaîne ajoutent implicitement un octet nul à la fin de la chaîne.