Suite à la question suivante: Comment l'adresse d'une array est-elle égale à sa valeur en C?
#include <stdio.h>
#define N 10
char str2[N]={"Hello"};
int main(){
printf("sizeof(str2): %d bytes\n", sizeof(str2));
printf("sizeof(&str2): %d bytes\n", sizeof(&str2));
return 0;
}
Sortir:
sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes
Je sais que str2
Seul est l'adresse du premier élément de tableau str2
. Et que lorsque str2
Est un argument de sizeof
il renvoie la taille de l'ensemble du tableau STR2.
De plus, &str2
Est également l'adresse du premier élément en arr str2
Mais de type différent (char (*)[N]
== pointeur au tableau). Mais comment &str2
Se comporte-t-il quand c'est un argument de sizeof
?
&str2
est un pointeur. Donc, vous voyez simplement la taille d'un pointeur sur votre plate-forme.
&str
et str
, lorsque str
est déclaré comme char str[10]
?Lire sizeof
opérateur:
6.5.3.4 la taille de l'opérateur, 1125:
[.____] Lorsque vous appliquez l'opérateursizeof
à un type de tableau, le résultat est le nombre total d'octets dans la matrice.
Donc, selon votre déclaration, sizeof(str2)
donne la taille complète de la matrice 10 octets (car n est défini 10, et la taille de caractère est de 1 octet).
[.____] alors que dans l'expression sizeof(&str2)
, &str2
est l'adresse du tableau et de la taille de l'adresse 4 octets de votre système. (Taille d'adresse May 8 octets dans certains systèmes E.g 64 bits).
De plus,
&str2
est également l'adresse du premier élément d'ARRstr2
?
Non, valeurs sage &str2
et str
sont identiques, mais sémantiquement les deux sont différents. L'une est une adresse d'un tableau de 10 caractères tandis que l'autre est une adresse d'un caractère.
ne différence que vous avez vue dans votre propre exemple que la manière dont ils sont des différences (et @ouah expliqua dans cette réponse).
str
est char[10]
&str
est char(*)[10]
Deuxièmement: Suivre le diagramme vous aidera à observer l'autre différence.
for declaration:
#define N 10
char str2[N] = {"Hello"};
str2 Array in memory is something like:
----------------------------------------
str
+----+----+----+----+----+----+----+----+----+----++----+
|'H' |'e' |'l' |'l' |'o' |'\0'|'\0'|'\0'|'\0'|'\0'|| '@'|
+----+----+----+----+----+----+----+----+----+----++----+
201 202 203 204 205 206 207 208 209 210 211
▲ ▲ ▲ ▲
| | | |
|(str2) (str2 + 1) |
| |
|-----------------------------------------------------|
|201 |
| |
| |
(&str2) = 201 (&str2 + 1) = 211
* assuming str address start from 201
* str[N] is 10 char long 201-210, partially initialized
* at uninitialized position, str2[i] = '\0'
* location 211 is unallocated, having garbage value,
access to this location is illegal-Undefined Behavior
Pour le diagramme ci-dessus, vous pouvez écrire un code:
#include <stdio.h>
#define N 10
int main(){
char str2[N]={"Hello"};
printf("\n %p, %p\n",str2, str2+1);
printf("\n %p, %p\n",(&str2), (&str2+1));
}
Sortir:
0xbf67e142, 0xbf67e143
0xbf67e142, 0xbf67e14c
AVIS La différence d'adresse de sortie de première ligne est un octet, mais dans la différence de deuxième ligne est de 10 octets car le pointeur de son tableau (comme indiqué ci-dessus dans le diagramme).
Selon les règles de mathématiques du pointeur lorsque vous ajoutez 1 à la variable du pointeur, il commence à suivre l'élément suivant de son propre type qui est la raison 10 différences d'octets car &str2
est une adresse de tableau.
Troisième différence:
En faisant *str2
, vous pouvez accéder au premier élément. Alors que *(&str2)
ne vous donnera pas un premier élément, mais il s'agit d'une adresse du premier élément.
Un exemple va aider ici:
#include <stdio.h>
#define N 10
int main(){
char str2[N]={"Hello"};
printf("\n%p %c, %p %c\n",str2, *(str2), *(&str2), **(&str2));
}
sortir:
0xbf587046 H, 0xbf587046 H
En sortie
str2 gives 0xbf587046
*(str2) H
*(&str2) 0xbf587046
**(&str2) H
Cela signifie que *(&str2) == str2
et la valeur est l'adresse. Et donc *(str2) = **(&str2)
valeurs est H
.
EDIT: ci-dessus, j'ai montré la différence entre &str
et str
_ str
est un tableau de type char[10]
.
char *str
et char str[]
et comment sont stockés en mémoireSupposons que nous ayons deux déclarations comme ci-dessous:
char *str1 = "hello";
char str2[] = "hello";
Dans les déclarations ci-dessus str1
est un pointeur sur char
, qui pointe vers un littéral à chaîne constante (en maintenant l'adresse du premier caractère h
dans "hello"
string).
Une chaîne en C est de char[N]
(tableau) Type C'est pourquoi sizeof("hello")
donne 6 car "hello"
chaîne est de 6 caractères de charrs (inclus \0
Nul, Terminaison des cordes, type de bonjour est char[6]
).
Dans la mémoire, vous "hello"
String est stocké comme ci-dessous:
str1 23 24 25 26 27 28
+----+ +----+----+----+----+----+----+
| 23 | | h | e | l | l | o | \0 |
+----+ +----+----+----+----+----+----+
+-----------▲
here address of hello string is first address = 23.
str1: is pointer capable to store address.
"hello" consists of 6 chars
char* str1 = "hello";
stocke essentiellement l'adresse de la chaîne Bonjour à la variable du pointeur str1
comme je l'ai montré ci-dessus sur la figure.
Remarque: si vous voulez récemment dans votre code, vous modifiez Modifier str1
pour pointer une autre chaîne. Mais vous ne pouvez pas modifier hello
string. Par exemple, le code suivant est valide:
char* str1 = "hello"; // str1 points to hello str1-->"hello"
str1 = "world"; //Now, str1 points to world str1-->"world"
Maintenant str1
pointe vers un autre monde de cordes constantes.
str1 93 94 95 96 97 98
+----+ +----+----+----+----+----+----+
| 93 | | w | o | r | l | d | \0 |
+----+ +----+----+----+----+----+----+
+-----------▲
here address of world string is first address = 93.
str1: value change to point string world.
Important à noter: str1
Points à des chaînes constantes, vous ne pouvez donc pas modifier la chaîne en accédant à/indexer l'emplacement de la mémoire par exemple str1[i] = 'A'
; Sera illégal parce que vous êtes écrit sur la mémoire en lecture seule et comportements de ceci ne sont pas définis au moment de l'exécution (bien qu'aucune erreur de compilation ne soit syntaxiquement).
Encore une fois parce que str1
est un pointeur sizeof(str1)
donnera 4 sur la même machine.
Mon code suivant et sa course:
#include <stdio.h>
int main(){
char* str1="Hello";
printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
str1 = "world";
printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
return 1;
}
Sortir:
str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4
Ainsi, pour attribuer une nouvelle chaîne, j'attribuais simplement une adresse de nouvelle chaîne. Mais je ne peux pas appeler strcpy()
qui va essayer d'écrire sur la lecture de la mémoire en lecture seule et qui est illégale.
Dans la deuxième déclaration char str2[] = "hello";
, str2[]
est une gamme \0
Terminé de caractères (ou de chaîne) mais pas du pointeur. Notez parce que dans cette taille de déclaration n'est pas donnée Taille par défaut Pourrons-nous cette taille de chaîne constante "Bonjour" 6. Type de str2
est char[6]
.
Lorsque nous faisons char str2[] = "hello";
Un tableau de charcuterie créé et Hello String sera copié dans ce tableau afin que str2
ne soit pas simplement pointeur, mais un tableau stockant une chaîne complète.
Sa conceptuellement comme.
str2:
103 104 105 106 107 108
+----+----+----+----+----+----+
| h | e | l | l | o | \0 |
+----+----+----+----+----+----+
Et dans ce cas ces derniers temps dans votre code, vous êtes non permet de faire str2[] = "world";
ou str2 = "world"
infecter une erreur de compilation.
Exemple de code:
#include<stdio.h>
int main(){
char str2[] = "hello";
str2[] = "world";
str2 = "world";
return 1;
}
Erreurs de compilation:
In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment
Lorsque ce tableau str2
n'est pas constant, nous pouvons modifier son contenu, par exemple, faire str2[2] = 'A'
est parfaitement valide. Nous pouvons également appeler Strcpy pour changer de contenu (et l'espace d'adressage ne changera pas)
strcpy(str2, "world");
str2:
103 104 105 106 107 108
+----+----+----+----+----+----+
| w | o | r | l | d | \0 |
+----+----+----+----+----+----+
Note world coped into same memory space, address of world and hello
string is name.
Exemple de code:
#include<stdio.h>
int main(){
char str2[] = "hello";
printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
str2[2] = 'A';
printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
strcpy(str2, "world");
printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
return 1;
}
Sortie:
str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6
Remarque: Les valeurs de chaîne sont différentes dans l'espace d'adressage même. sizeof(str2)
= 6 parfaitement compris de la réponse plus ancienne qui est la taille de la matrice en octets.
Pour lire une description similaire sur une matrice à 2 dimensions, lisez: différence entre char* str[]
et char str[][]
et comment les deux magasins en mémoire?
str2
Est de type char [10]
(I.e, tableau 10 of
Char`)
&str2
Est de type char (*)[10]
(i.e., pointeur à un tableau 10
De char
).
Donc, sizeof (&str2)
donne la taille d'un objet de type pointeur char (*)[10]