簡體   English   中英

sizeof(&array) 返回什么?

[英]What does sizeof(&array) return?

跟隨這個問題: 為什么數組的地址等於它在 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;
}

輸出:

sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes

我知道str2本身就是數組str2第一個元素的地址。 並且當str2sizeof的參數時,它返回整個數組 str2 的大小。

此外, &str2也是 arr str2第一個元素的地址,但類型不同( char (*)[N] == 指向數組的指針)。 但是當&str2sizeof的參數時,它的行為如何?

&strstr之間的區別,當str被聲明為char str[10]

讀取sizeof運算符:

6.5.3.4 sizeof 運算符,1125:
sizeof運算符應用於數組類型時,結果是數組中的總字節數。

因此,根據您的聲明, sizeof(str2)給出了 10 個字節的完整數組大小(因為 N 定義為 10,而 char 大小為 1 個字節)。
而在表達式sizeof(&str2)&str2是一個數組的地址,並且該地址的大小在您的系統上是 4 個字節。 (地址大小在某些系統中可能是 8 個字節,例如 64 位)。

另外, &str2也是 arr str2第一個元素的地址?

&str2str在值方面是相同的,但在語義上是不同的 一個是 10 個字符數組的地址,另一個是一個字符的地址。

您在自己的示例中看到的一個區別是(@ouah 在回答中對此進行了解釋)。

  • str類型是char[10]
  • &str類型是char(*)[10]

第二:遵循圖表將幫助您觀察其他差異。

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

對於上圖,您可以編寫如下代碼:

#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));
}  

輸出:

 0xbf67e142, 0xbf67e143

 0xbf67e142, 0xbf67e14c

鍵盤鏈接:

請注意,在第一行,輸出地址相差一個字節,但在第二行中,相差 10 個字節,因為它是數組的指針(如上圖所示)。

根據指針算法的規則,當你給一個指針變量加 1 時,它開始指向它自己類型的下一個元素。 這就是 10 字節差異的原因,因為&str2是一個數組地址。

第三個區別:

通過執行*str2您可以訪問 thr 第一個元素。 *(&str2)不會給你第一個元素,而是給你第一個元素的地址。

一個例子將在這里有所幫助:

#include <stdio.h>
#define N 10    
int main(){
   char str2[N]={"Hello"};
   printf("\n%p %c, %p %c\n",str2, *(str2), *(&str2), **(&str2));
}  

輸出:

0xbf587046 H, 0xbf587046 H

鍵盤鏈接

在輸出中

str2 gives  0xbf587046 
*(str2)     H 
*(&str2)    0xbf587046 
**(&str2)   H 

這意味着*(&str2) == str2並且 value 是地址。 因此*(str2) = **(&str2)值是H

編輯:上面我展示了&strstr之間的區別,其中strchar[10]類型的數組。

char *strchar str[]之間的區別以及兩者在內存中的存儲方式

假設我們有如下兩個聲明:

char *str1 = "hello";   
char str2[] = "hello";  

在上面的聲明中, str1是一個指向char的指針,它指向一個常量字符串文字(通過保存"hello"字符串中第一個字符h地址)。

C 中的字符串是char[N] (數組)類型,這就是sizeof("hello")給出 6 的原因,因為"hello"字符串是 6 個字符長的數組(包括\\0 nul,字符串終止,hello 類型是char[6] )。

在內存中,您的"hello"字符串存儲如下:

 str1         23   24   25   26   27   28
+----+      +----+----+----+----+----+----+
| 23 |      | h  | e  |  l | l  | o  | \0 |    
+----+      +----+----+----+----+----+----+
   +-----------▲

here the address of the hello string is the first address = 23.  
str1: is a pointer capable of storing an address. 
"hello" consists of 6 chars

char* str1 = "hello"; 基本上將字符串 hello 的地址存儲到指針變量str1 ,如上圖所示。

注意:如果需要,您可以將str1更改為指向其他字符串。 但是你不能修改hello字符串。 例如下面的代碼是有效的:

 char* str1 = "hello";  // str1 points to hello  str1-->"hello"
 str1 = "world";  //Now, str1 points to world  str1-->"world"

現在str1指向其他常量字符串世界。

 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. 

需要注意的重要事項: str1指向常量字符串,因此您不能通過訪問/索引內存位置來修改字符串,例如str1[i] = 'A' ; 將是非法的,因為您在只讀內存上寫入並且在運行時未定義它的行為(盡管沒有編譯錯誤,因為它在語法上是正確的)。

同樣,因為str1是一個指針sizeof(str1)將在同一台機器上給出 4。

我的以下代碼及其運行:

#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;
}  

輸出:

str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4

鍵盤鏈接

因此,要分配一個新字符串,我只需分配一個新字符串的地址。 但是我不能調用strcpy() ,它會嘗試在只讀內存位置上寫入並且這是非法的。

在第二個聲明中char str2[] = "hello"; , str2[]是一個以\\0結尾的字符(或字符串)數組,但不是指針。 注意,因為在這個聲明中 size 沒有給出默認 size ,我們看到常量字符串“hello”的大小是 6。 str2類型是char[6]

當我們做char str2[] = "hello"; 一個字符數組被創建,hello 字符串將被復制到該數組中。 所以str2不僅僅是一個指針,而是一個存儲完整字符串的數組。

從概念上講就像

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | h  | e  |  l | l  | o  | \0 |    
      +----+----+----+----+----+----+

在這種情況下,最近在你的代碼你不能str2[] = "world"; str2 = "world" ,這將是編譯時錯誤。

示例代碼:

#include<stdio.h>
int main(){
 char str2[] = "hello";
 str2[] = "world";
 str2 = "world"; 
 return 1; 
}

編譯錯誤:

In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment

代碼景觀鏈接

如果這個數組str2不是常量,我們可以修改它的內容,例如執行str2[2] = 'A'是完全有效的。 我們也可以調用strcpy來改變內容(而且地址空間不會改變)

       strcpy(str2, "world");

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | w  | o  |  r | l  | d  | \0 |    
      +----+----+----+----+----+----+

      Note that when "world" is copied into a same memory space, the addresses of both "world" and "hello"
      string are the same.  

代碼示例:

#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; 
}

輸出:

str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6

鍵盤鏈接

注意:相同地址空間的字符串值是不同的。 sizeof(str2) = 6 從舊答案中可以完全理解,即數組的大小(以字節為單位)。

要閱讀有關二維數組的類似描述,請閱讀: char* str[]char str[][]之間的區別以及兩者如何存儲在內存中?

&str2是一個指針。 所以你只是在你的平台上看到一個指針的大小。

str2char [10]類型(即 char` 的數組10 of

&str2char (*)[10] (即指向char數組10的指針)。

所以sizeof (&str2)產生指針類型char (*)[10]對象的大小

2021年讀者:

可以將char arr[10]視為在幕后聲明兩個對象:

  • 指向數組第一個元素的 const 指針char * const arr (所以你不能重新分配給arr
  • arr相關聯的大小[10] ,因此您可能會在索引超出范圍時收到警告。

以上分別引出了兩個事實:

  • 指針算術被設計為數組移動,因此在對arr進行指針算術時僅使用信息char * const arr arr

    因此arr上的指針算術將在一個char偏移,而不是在char [10] ,即arr+1指向arr[1]

  • 一些操作,例如sizeof(arr)&arr ,利用所有信息char * const arr[10]

    所以sizeof(arr)返回sizeof(char) * 10 (或sizeof(*arr) * 10 ,更便攜),即在此操作中使用與arr關聯的大小[10]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM