char buffer[4];
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl;
當我運行這段代碼時,第一行是緩衝區中第一個元素的十六進制地址。第二行是四個問號(除非我把它當作空指針)。打印&some_buf [0]和&some_buf如何提供不同的輸出?
第二個陳述與第一個陳述有什麼不同?(在語義上它們是相同的?)? 爲什麼第二行顯示爲問號而不是隨機垃圾字符?
char buffer[4];
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl;
當我運行這段代碼時,第一行是緩衝區中第一個元素的十六進制地址。第二行是四個問號(除非我把它當作空指針)。打印&some_buf [0]和&some_buf如何提供不同的輸出?
第二個陳述與第一個陳述有什麼不同?(在語義上它們是相同的?)? 爲什麼第二行顯示爲問號而不是隨機垃圾字符?
&buffer
以適當的指針類型爲您提供緩衝區的地址。該類型是char (*)[4]
。
&buffer[0]
給你第一緩衝元件(char
)的地址,所以該地址是char*
類型。
標準流類具有處理char const*
的超載,但沒有處理char (*)[4]
的超載。然而,對於指針來說有一般的超載,它接受void*
。所以指向數組的指針被隱式轉換爲void*
,並傳遞給該過載。因此您可以看到緩衝區的地址。
在第二種情況下,如果buffer
已正確初始化,您會看到它的內容被打印(「c-string」超載是什麼)。但是,由於您沒有初始化它,因此您的代碼具有未定義的行爲。僅僅嘗試打印緩衝區沒有明確的結果。
這正是我所期待的。我想問一個後續問題。 char(*)[4]的指針和char(*)[10]的指針之間會有區別嗎? C++不會跟蹤數組的長度,爲什麼我們不能把它稱爲char(*)[n]呢? – Locus
@Locus - C++最明確地記錄了大小。大小是類型的一部分(例如'char [10]')。你混淆的是陣列衰減。 – StoryTeller
是的,你是對的,我甚至不知道陣列衰減是什麼,並認爲這是'正常'的情況。 – Locus
&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
'字符*'的處理從'無效*'不同與'的std :: ostream的&運算<<(標準:: ostream的&,T)'。 – user0042
「指向T的數組指針」和「指向T的指針」在語義上並不相同。在這種情況下,'buffer'相當於'&buffer [0]',而不是'&buffer'。 – molbdnilo
@molbdnilo,是的!這是我理解失敗的地方。我認爲這兩個語句都是「緩衝區第一個元素的內存地址」,而不是「T指針指針」和「T指針」,但現在我知道了。 – Locus