[英]Why does cout << &r give different output than cout << (void*)&r?
這可能是一個愚蠢的問題,但是我是C ++的新手,所以我仍然在愚弄基本知識。 測試指針時,遇到了無法產生預期輸出的問題。
當我運行以下命令時:
char r ('m');
cout << r << endl;
cout << &r << endl;
cout << (void*)&r << endl;
我期望這樣:
m
0042FC0F
0042FC0F
..但是我得到了:
m
m╠╠╠╠ôNh│hⁿB
0042FC0F
我在想,也許因為r
的類型為char
, cout
會將&r
解釋為char*
,[出於某種原因]輸出指針值-包含r
的地址的字節-作為一系列chars
,但是為什么會這樣呢?第一個將是m
,即指向的地址的內容 ,而不是指針地址的第一個字節的char
表示。.好像cout
將&r
解釋為r
而不是僅輸出'm'
,它繼續輸出更多字符-從隨后的11個存儲器地址的字節值解釋。為什么? 為什么11?
我在64位Win7上使用MSVC ++(Visual Studio 2013)。
附言:我在這里得到了很多正確答案(如預期的那樣,考慮到問題的瑣碎性質)。 由於我只能接受一個,因此我將其設為第一個看到的對象。 但是,謝謝大家。
因此,總結並擴展我的問題中提到的本能理論:
是的, cout
確實將&r
解釋為char*
,但由於char*
是C ++中的“特殊事物”,從本質上講是指以空終止的字符串 (而不是指向單個char
的指針 ),因此cout
會嘗試打印出該字符串通過輸出chars(從r
的內存地址的字節內容開始解釋)直到遇到'\\0'
為止。 這就解釋了11個額外的字符(恰好又花了11個字節才能擊中NUL
)。
為了完整起見-相同的代碼,但是用int
代替char
,按預期執行:
int s (3);
cout << s << endl;
cout << &s << endl;
cout << (void*)&s << endl;
產生:
3
002AF940
002AF940
對於char*
字符串,有一個operator<<
重載。 這將輸出以零結尾的字符串,而不是地址。 由於要傳遞此重載的指針不是以Null結尾的字符串,因此當operator<<
越過緩沖區的末尾時,也會得到未定義的行為。
相反, void*
重載將打印地址。
char *
是C++
一種特殊東西,它繼承自C
在大多數情況下,它是C
風格的字符串。 它應該指向以0
(NUL字符'\\0'
)結尾的char
數組。
因此,它嘗試打印此內容,然后在'm'
之后繼續到內存中,尋找終止的'\\0'
。 這使其打印一些隨機垃圾。 這稱為未定義行為 。
因為有一個operator<<
的重載,它使用const char
指針作為第二個參數並輸出一個字符串。 帶有void
指針的重載僅輸出地址。
因為operator<<
根據數據類型被重載。
如果給它一個char
,它將假定您想要該字符。
如果給它一個void*
,則假定您要一個地址。
但是,如果給它一個char*
,它將把它作為C樣式的字符串並嘗試將其輸出。 由於C ++的原始意圖是“帶類的C”,因此必須處理C樣式的字符串。
最后得到所有垃圾的原因僅僅是因為盡管您對編譯器進行了斷言,但實際上它不是 C樣式的字符串。 具體來說,不能保證在結尾處有一個以字符串結尾的NUL字符,因此輸出例程將僅輸出其后在內存中發生的任何事情。
這可能會起作用(如果那里有一個NUL),它可能會打印出亂碼(如果附近有一個NUL),或者它可能會掉下來(如果在存儲到內存之前沒有NUL,則無法讀取)。 這不是您應該依賴的東西。
char *
通常(通常是偶數)是指向C樣式的以null終止的字符串(或字符串文字)的指針,並被ostream視為此類。 相反, void *
明確表示需要一個指針值。
char const*
和void const*
的輸出運算符( operator<<()
)已重載。 當傳遞char*
, char const*
char*
的重載是更好的選擇。 此重載需要一個指向以空終止的字符串開頭的指針。 給它一個指向單個char
的指針,即,您得到未定義的行為。
如果您想嘗試一個定義明確的示例,則可以使用
char s[] = { 'm', 0 };
std::cout << s[0] << '\n';
std::cout << &s[0] << '\n';
std::cout << static_cast<void*>(&s[0]) << '\n';
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.