首先,考慮這個例子:
#include <iostream>
using namespace std;
int main()
{
cout << ("123" == "123");
}
我期望什么:由于“123”是一個const char*,我期望比較這些字串的地址(如這些答案之一所述)。
...因為
!=and==只會比較這些字串的基地址。不是字串本身的內容。
但輸出仍然是1. 好吧,我們實際上不知道如何比較兩個純右值物件的地址(或者至少我不明白它是如何完成的)。所以讓我們將這些字串宣告為變數,看看會發生什么:
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1230";
cout << (a == b);
}
輸出仍然是1. 所以const char*弦不會衰減?或者編譯器設法做一些優化并只為一個字串分配記憶體?好的,讓我們盡量避免它們:
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1231";
b = "1230";
cout << (a == b);
}
結果還是一樣。這讓我覺得const char*真的不朽。但這并沒有讓我的生活變得更簡單。那么如何const char*比較s呢?
為什么這里的輸出是1:
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1231";
cout << (a > b);
}
ab在詞法比較方面小于,但這里a更大。那么const char*s的比較是如何實作的呢?
uj5u.com熱心網友回復:
是的,鏈接的答案是正確的。operator==指標只是比較地址,而不是它們的內容。
此外,編譯器可以自由地(但不是必需)洗掉重復的字串文字,因此所有出現的字串文字都是同一個物件,具有相同的地址。這就是你觀察到的,重新分配b = "1230";不會阻止它。
[lex.string.14]對字串字面量求值會產生一個具有靜態存盤持續時間的字串字面量物件,從上面指定的給定字符初始化。是否所有字串文字都是不同的(即存盤在非重疊物件中)以及字串文字的連續計算是否產生相同或不同的物件是未指定的。
應該const char*衰減到什么程度?陣列會衰減,指標不會。
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1231";
cout << (a > b);
}
回傳1只是因為a碰巧指向比 更高的地址b,因此沒有進行字典序比較。只需使用std::string或std::string_view如果您需要。
uj5u.com熱心網友回復:
文字字串的存盤細節在 C 標準中完全沒有規定(除了它們的生命周期),完全由編譯器決定。例如:
const char *a="ABCDEFG";
const char *b="DEFG";
智能編譯器完全有可能只生成一個字串,并將第二個指標設定為指向字串的中間。
來自不同.cpp檔案的相同文字字串也可能在最終鏈接的可執行檔案中只生成一個字串,并且這兩個字串最初以.cpp完全不同的方式編譯,最終具有相同的實際指標值。
同樣,指標比較也是為 C 標準中未明確指定的所有其他情況定義的實作。指標比較具有定義的行為,主要用于指向同一陣列或向量成員的指標,否則通常完全未指定。在 C 標準中,有一些方法可以實作指標的全序,但這與此處無關。
總而言之:否則,您不能期望任何指標值具有任何特定行為或特定含義。
uj5u.com熱心網友回復:
在這個比較中
"123" == "123"
具有該型別的字串文字const char[4]被隱式轉換為指向它們的第一個元素的指標,并比較這些指標。
結果取決于編譯器選項,這些選項指定相同的字串文字是作為一個字串文字存盤還是作為單獨的字串文字存盤。
至于這個節目
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1231";
cout << (a > b);
}
那么您不能將運算子 > 與不指向同一陣列元素的指標一起使用。這種比較是未定義的。
比較的結果取決于編譯器將字串文字放入字串文字池中的順序。
uj5u.com熱心網友回復:
我希望比較這些字串的地址(如這些答案之一所述)。
正確,這就是 C 和 C 中發生的情況。當在 C 和 C 中比較 C 字串(字符陣列)或字串文字時,編譯器應該只比較它們的地址。
或者編譯器設法做一些優化并只為一個字串分配記憶體?
是的!恰恰。編譯器看到"1230"兩次并且可能(在您/我們的情況下,確實如此,這就是我們看到這種行為的原因)只是在下面的代碼中為它們在相同的確切記憶體位置使用相同的確切字串。因此,它們具有相同的地址。這是 C 和 C 編譯器可能為您做的一個很好的優化。
#include <iostream>
using namespace std;
int main()
{
const char* a = "1230";
const char* b = "1230";
cout << (a == b);
}
更進一步:
為您進行優化的事實意味著您可以愉快地撰寫如下內容,即使在記憶體受限的嵌入式系統上,知道使用的程式空間不會因每次使用字串文字的大小而增加字串字面量:
printf("some very long string\n");
printf("some very long string\n");
printf("some very long string\n");
printf("some very long string\n");
"some very long string" 僅一次存盤在記憶體中。
話雖如此,如果您對該字串進行單個字符更改,編譯器可能會選擇使其成為記憶體中的新字串,因此在上述情況下,您最好這樣做:
constexpr char MY_MESSAGE[] = "some very long string\n";
// OR:
// #define MY_MESSAGE "some very long string\n"
printf(MY_MESSAGE);
printf(MY_MESSAGE);
printf(MY_MESSAGE);
printf(MY_MESSAGE);
也可以看看:
- 為什么(僅)某些編譯器對相同的字串文字使用相同的地址?
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/362490.html
下一篇:指向指標C的指標
