2017-08-13 82 views
0
char buffer[4]; 
std::cout << &buffer << std::endl; 
std::cout << &buffer[0] << std::endl; 

當我運行這段代碼時,第一行是緩衝區中第一個元素的十六進制地址。第二行是四個問號(除非我把它當作空指針)。打印&some_buf [0]和&some_buf如何提供不同的輸出?

第二個陳述與第一個陳述有什麼不同?(在語義上它們是相同的?)? 爲什麼第二行顯示爲問號而不是隨機垃圾字符?

+2

'字符*'的處理從'無效*'不同與'的std :: ostream的&運算<<(標準:: ostream的&,T)'。 – user0042

+0

「指向T的數組指針」和「指向T的指針」在語義上並不相同。在這種情況下,'buffer'相當於'&buffer [0]',而不是'&buffer'。 – molbdnilo

+0

@molbdnilo,是的!這是我理解失敗的地方。我認爲這兩個語句都是「緩衝區第一個元素的內存地址」,而不是「T指針指針」和「T指針」,但現在我知道了。 – Locus

回答

7

&buffer以適當的指針類型爲您提供緩衝區的地址。該類型是char (*)[4]

&buffer[0]給你第一緩衝元件(char)的地址,所以該地址是char*類型。

標準流類具有處理char const*的超載,但沒有處理char (*)[4]的超載。然而,對於指針來說有一般的超載,它接受void*。所以指向數組的指針被隱式轉換爲void*,並傳遞給該過載。因此您可以看到緩衝區的地址。

在第二種情況下,如果buffer已正確初始化,您會看到它的內容被打印(「c-string」超載是什麼)。但是,由於您沒有初始化它,因此您的代碼具有未定義的行爲。僅僅嘗試打印緩衝區沒有明確的結果。

+0

這正是我所期待的。我想問一個後續問題。 char(*)[4]的指針和char(*)[10]的指針之間會有區別嗎? C++不會跟蹤數組的長度,爲什麼我們不能把它稱爲char(*)[n]呢? – Locus

+1

@Locus - C++最明確地記錄了大小。大小是類型的一部分(例如'char [10]')。你混淆的是陣列衰減。 – StoryTeller

+0

是的,你是對的,我甚至不知道陣列衰減是什麼,並認爲這是'正常'的情況。 – Locus

4

&buffer是緩衝區的地址。 &buffer[0]是緩衝區中第一個字符的地址。在這裏你的情況是一個垃圾值,因爲你沒有初始化它。嘗試初始化:

char buffer[] = "Hello there!"; 
std::cout << &buffer << std::endl; 
std::cout << &buffer[0] << std::endl; // print from first element to the end(until the first null-character) 
std::cout << &buffer[4] << std::endl; // print from fifth element to the end 

輸出:

0018FF38 
Hello there! 
o there! 
  • 我認爲這是osstream insertion operator <<一個問題,假定你傳遞一個char*,你傳遞給它一個字符的地址所以我猜這是UB。

  • 爲了讓你必須將它轉換爲void*字符的地址:

    std::cout << static_cast < void* >(&buffer[0]) << std::endl; 
    std::cout << static_cast < void* >(&buffer[1]) << std::endl; 
    

輸出:

0018FF38 
    0018FF39 

要確認這是一個ostream <<問題,嘗試使用printf

printf("&buffer[0]: %p \n", &buffer[0]); 

輸出:

&buffer[0]: 0018FF38