web-dev-qa-db-fra.com

Qu'est-ce que Tailleof (& Array) revient?

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?

31
user1980750

&str2 est un pointeur. Donc, vous voyez simplement la taille d'un pointeur sur votre plate-forme.

19

Différence entre &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érateur sizeof à 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'ARR str2?

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).

  • type de str est char[10]
  • type de &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

A Lien pour CODEPAD :

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

Link CodePad

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].

Différence entre char *str et char str[] et comment sont stockés en mémoire

Supposons 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

Link CodePad

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

liaison codescape

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

Link CodePad

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?

108
Grijesh Chauhan

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]

8
ouah