[英]If I convert a derived pointer to a base pointer, are the two pointers guaranteed to have the same value?
[英]Two string literals have the same pointer value?
當我使用MinGW運行此程序時,我輸出為“=”
#include<iostream>
using namespace std;
int main()
{
char *str1 = "Hello";
char *str2 = "Hello";
if(str1==str2)
cout<<"=";
else
cout<<"!=";
return 0;
}
但是,從邏輯上講,它應該是!=,因為這些是指針,它們指向不同的內存位置。 當我在Turbo C ++中運行此代碼時,我得到了!=
你是對的,他們是指針。 但是,它們是否指向不同的位置取決於實施。 編譯器只存儲一次字符串文字並在代碼中使用它的地址時使用它的地址是完全有效的。
無法保證兩個指針指向不同的內存位置。 也許是因為優化,或者編譯器使用自己的規則......行為是“實現定義”。
根據標准(C ++11§2.14.5字符串文字):
是否所有字符串文字都是不同的(即存儲在非重疊對象中)是實現定義的。
這是預期的結果。 您可以通過查看基礎程序集來驗證這一點。 例如,如果我構建:
g++ -S ptr.c
然后你可以在文件輸出(ptr.s)中看到以下內容:
.file "ptr.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "Hello\0" ; Note - "Hello" only appears once in
; this data section!
LC1:
.ascii "=\0"
LC2:
.ascii "!=\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
[... some stuff deleted for brevity ...]
LCFI5:
call ___main
movl $LC0, -12(%ebp) ; This sets str1
movl $LC0, -8(%ebp) ; This sets str2
movl -12(%ebp), %eax
我評論了兩個關鍵位 - 在底層代碼的rdata部分只有一個'Hello'的外觀,你可以看到str1和str2都設置在最后,兩者都指向同一個標簽: LC0
。 這是因為'Hello'是一個字符串文字,重要的是,它是不變的 。
正如其他人所指出的那樣 - 根據標准,這是完全合法的。
像"Hello"
這樣的字符串文字的類型是const char數組 ,因此,您指向兩個指針,指向不允許更改的內容。
C ++標准使編譯器可以自由地將相同的常量值合並在一起(請注意,編譯器不需要這樣做)。
相關:因此聲明無效,必須修改為:
const char *str1 = "Hello";
const char *str2 = "Hello";
或者如果你想
char const *str1 = "Hello";
char const *str2 = "Hello";
從右到左閱讀時讀得很好:
str1 is a pointer to const char
。
char *str1 = "Hello";
- 這條線,雖然允許(由許多編譯器),實際上是一個壞主意。 它基本上只允許與C向后兼容,實際寫入* str1會導致未定義的行為。 我建議找到編譯器設置,當你這樣做時會給你警告,如果你的編譯器沒有這樣的警告找到一個新的編譯器。
C ++標准為編譯器和執行環境提供了關於"String literals"
存儲位置的荒謬自由。 他們可以直接使用指向"String literals"
的"literal"
部分的指針作為"literal"
的指針值,並將它們存儲在您嘗試編輯它們時會出現段錯誤的內存中並不意外。
注意char buf1[] = "Hello";
做一些與char* str1 = "Hello";
根本不同的事情char* str1 = "Hello";
:它實際上用字符{'H','e','l','l','o','\\0'}
初始化緩沖區buf1
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.