指標與字串


在〈字元陣列與字串〉談過 C 風格字串,本質上就是個字元陣列,而陣列名稱具有指標性質,那可以如下建立字串嗎?

char *text = "hello";

以前可以,不過使用 MinGW-w64,GNU 編譯器版本 8.1.0 編譯的話,會有以下警訊:

warning: ISO C++ forbids converting a string constant to 'char*'

text 儲存了字串常量的位址值,然而字串常量建立的內容是唯讀的,必須如下才不會有警訊:

const char *text = "hello";

上述方式中,text 只是個型態為 const char* 的指標,是與以下不同的,底下建立的 text 內容並不是唯讀的,因為 text 是個陣列,text 是將 "hello" 複製至各索引處:

char text[] = "hello";

對於 wchar_t 等其他為了支援 Unicode 的型態,都有這類特性。

然而,無論是哪個形式,都可以傳遞位址,例如:

char text1[] = "hello";
const char *text2 = "hello";

const char *text = text1; // OK
text = text2;             // OK

不過,底下不行:

char text1[] = "hello";
const char *text2 = "hello";

char *text = text1; // OK
text = text2;       // error: invalid conversion from 'const char*' to 'char*'

錯誤該行如果真的想通過編譯,就必須明確告訴編譯器,你要去除 const 修飾,也就是使用 const_cast

char text1[] = "hello";
const char *text2 = "hello";

char *text = text1;               // OK
text = const_cast<char*>(text2);  // OK

會需要這麼做的情況,可能是在使用一些舊的函式,它們在參數上宣告的是 char*,而不是 const char*

那麼,如何建立字串陣列呢?

#include <iostream> 
#include <cstring>
using namespace std; 

int main() {
    const char *names[] = {"Justin", "Monica", "Irene"};

    for(auto name : names) {
        cout << name << endl;
    }

    return 0; 
}

留意一下底下的不同:

const char *names1[] = {"Justin", "Monica", "Irene"};
char names2[][10] = {"Justin", "Monica", "Irene"}; 

name1 的每個元素,儲存了各個字串常量的位址值;然而,name2 是有三個長度為 10 的 char 陣列,並複製了各個字串常量的 char

在 C++ 中使用 C 風格字串是比較麻煩的,可以的話建議使用 string