2017-02-06 27 views
1

我測試了相同的字符串內容「abc」使用sizeof()。我的職責是這樣的:C:不同的字符串定義,我得到不同的大小使用sizeof()

int main(void){ 
    char* pass1 = "abc"; 
    char pass2[] = "abc"; 
    char pass3[4] = "abc"; 
    char pass4[] = ""; 

    scanf("%s", pass4); 

    printf("sizeof(pass1) is: %lu\n", sizeof(pass1)); 
    printf("sizeof(pass2) is: %lu\n", sizeof(pass2)); 
    printf("sizeof(pass3) is: %lu\n", sizeof(pass3)); 
    printf("sizeof(pass4) is: %lu\n", sizeof(pass4)); 

    return 0; 
} 

我輸入 「ABC」 爲PASS4,輸出是這樣的:

sizeof(pass1) is: 8 
sizeof(pass2) is: 4 
sizeof(pass3) is: 4 
sizeof(pass4) is: 1 

我期待所有的4S。我認爲上面的4個字符串定義是相同的。

爲什麼sizeof(pass1)返回8?爲什麼sizeof(pass4)是1?

+3

'sizeof'產生'size_t'類型的結果。 'size_t'的正確格式是'「%zu」'。 –

+0

這是數組不是指針的時代之一......它們在傳遞給函數時會轉移到指針,但是會丟失這個大小的信息......實際上,一個常見的範例使用它來查找數組中的元素數... –

+2

[要打印'size_t'使用%zu](http://stackoverflow.com/q/940087/995714)。使用錯誤的格式說明符調用未定義的行爲 –

回答

3

當你在指針類型上使用sizeof時,你會得到內存地址的大小(以字節爲單位)。在這種情況下,8是地址的大小(以字節爲單位)。 sizeof靜態分配C中的只讀字符串將返回字符串的實際大小(包括空字節)。

+0

我以爲指針pass1指向8位字符型內存地址。我從來沒有爲該字符串定義8字節的內存地址。 –

+0

@DiWang依賴於編譯器和平臺,也許你在x64平臺上使用64位編譯器。 你可以檢查sizeof(void *),sizeof(char *),sizeof(double *)或任何指針類型,它們都是相同的。 –

+0

謝謝,sizeof(char *)在我的電腦上測試過。 –

0

在此聲明

char* pass1 = "abc"; 
在用作初始值的右側

存在具有大小等於4字符串文字的字符陣列具有類型字符陣列。考慮到字符串文字包括終止零。您可以檢查此數組用於初始化指針以下方式

printf("sizeof(\"abc\") is: %zu\n", sizeof("abc")); 

在聲明。用作指針的初始化程序時,數組將隱式轉換爲指向其第一個元素的指針。

因此指針pass1指向字符串文字​​的第一個元素。系統中指針本身的大小等於8個字節。

在這些declerations

char pass2[] = "abc"; 
char pass3[4] = "abc"; 

字符串文字用於初始化數組。在這種情況下,數組中的每個元素都由字符串文字的相應元素初始化。數組的所有其他元素都是零初始化的。如果沒有指定數組的大小,則從初始化程序的數量計算。因此,在此聲明

char pass2[] = "abc"; 

陣列pass2將有4個元素,因爲sgtring字面提供四個初始化。

在此聲明

char pass3[4] = "abc"; 

有明確指定的陣列具有4個元素。

因此,兩個數組的大小等於4,首先聲明的指針的大小爲8個字節。

2

sizeof給出了其操作數的大小。要了解您看到的結果,您需要了解pass1,pass2,pass3pass4實際上是什麼。

pass1是指向字符的指針(即char *),因此sizeof pass1給出了指針(包含內存地址而不是數組的變量)的大小。你的編譯器就是8。指針的大小是實現定義的,所以這可能會給不同的編譯器帶來不同的結果。您已初始化pass1因此它指向字符串文字​​的第一個字符的事實不會更改pass1被聲明爲指針而不是數組的事實。

pass2是使用文本​​哪個數組初始化 - 按照慣例 - 用C表示使用的4個字符(的三個字母'a''c',加上與值零('\0')附加字符陣列

pass3也是四個char數組,因爲它被聲明這樣char pass3[4] = <etc>。如果你做了char pass3[4] = "abcdef",你還是會發現sizeof pass34(和pass3的4個元素將'a''d'(與其他甜心cter 'e','f'和在字符串文字"abcdef"中未用於初始化pass3)。

由於pass2pass3都是四個字符的數組,它們的大小爲4(通常,數組的大小是數組元素的大小乘以元素的數量)。該標準將sizeof char定義爲1,並且1*4具有值4

pass4使用文字""進行初始化。該字符串文字使用值爲'\0'(且之前沒有字符,因爲沒有位於雙引號之間)的單個字符表示。因此,pass4的大小爲1的原因與pass2的大小爲4相同。

+0

但是pass4已被替換爲「abc」,\ 0被覆蓋。大小再次如何?我已經測試了strlen(pass4),它返回3,但sizeof(pass4)返回1. –

+0

'scanf(「%s」,pass4)'(我會指出你在我給出這個答案後插入)給出undefined行爲,除非用戶在換行符之前不輸入任何字符。這意味着任何事情都可以發生。在實踐中,如果你輸入'abc',它會覆蓋'pass4'後面的任何內存。這並不會改變'pass4'的大小 - 它僅僅意味着你的代碼會覆蓋'pass4'結尾的內存。由於'strlen()'不斷遍歷內存,直到找到一個''\ 0'',它會報告'4',但這是偶然。 – Peter

相關問題