字串陣列與指標

2021-04-25 16:06:07 字數 3024 閱讀 3542

思維**於一道題

char str1       = "abc";

char str2       = "abc";

const char str3 = "abc";

const char str4 = "abc";

const char* str5  = "abc";

const char* str6  = "abc";

cout << boolalpha << ( str1==str2 ) << endl; // 輸出什麼0?

cout << boolalpha << ( str3==str4 ) << endl; // 輸出什麼0?

cout << boolalpha << ( str5==str6 ) << endl; // 輸出什麼1?

可以明白 靜態分配的陣列(name)有唯一的位址空間,因為它在靜態分配的時候就分配好了。

此題的關鍵不在於5.6的const屬性,即使沒有const仍相等。因為指標是動態分配的(就我的理解)。

就是說!它雖然跟陣列名同樣為指標,可是卻是行為完全不同的兩個東西!!

我想這可能根編譯器或者c語言的不夠規範有關。

眾所周知,在引用陣列名的時候它會自動退化為指標。根據大家對指標的理解,也知道:指標,實際上

就是儲存了乙個目標位址的東西。再準確點說,也就是個位址值,類似於「0012ff60」的東西。

但是為什麼,我們在輸出的時候,單純的輸出指標——特別的,這裡有兩種情況。

首先,我實驗了const char *p = "abc";

當指標指向乙個陣列的時候,cout《然而這樣的方便也是災難性的——它給許多人造成了困惑。它的不規範,讓我們也置疑c語言的嚴密性。

接下來,我又證明了我這一想法——

我使用單個元素而不是使用陣列來為指標賦值——

int a = 31;

int *b = &a;

cout《結果跟我想象得一樣,輸出的是兩個相同位址「0012ff60」……我很滿意,這證明為了前面的想法。

特別的,我開始用的不是int,是char。輸出的是兩個相同的亂碼。這讓我又多了乙個資訊——由於int是

4位元組的(32位),而char是1位元組(8位)。我以為,在32位機上,不足32位的結構的位址會出問題——

但是我換成short又沒問題了……所以我想只跟char的編碼有關,為此我沒做更深入研究。

最後,我想知道它們(陣列、指標)的大小到底是多少。

眾所周知,指標大小都是4。

char c = "1234567890";

char *a = c;

不要小看這兩個句子。在任何時候,只要你定義的時候它是乙個陣列(c),編譯器就永遠會記住它。

無論你引用它的名字(c),使它退化成乙個指標,還是在任何時候使用sizeof(c),它永遠都是乙個陣列,

大小永遠是固定的。

而指標,只要你定義的是乙個指標,那麼它大小永遠就是4。

這一點只看你在定義時的行為。

就好像const char *h = "abcdefg";

最後我要強調的,上面這個句子其實很危險。因為要給乙個指標賦值,必須給它乙個位址!是位址!。

安全的做法,是我們最好先靜態或動態建立乙個物件。比如char a[10]; 或 char *a = new char[10]。

這樣,我們再在其中賦值——只能a[0]、a[1]、a[2]、a[3]……挨著複製,比較麻煩。但是至少我們

使它(陣列)的位址可見!它們是唯一的,並且可以安全地釋放(靜態的自動,動態的手動delete)。

指標本身是不能建立物件的。上面這個句子const char *h = "abcdefg";實際上做了兩件事——

建立了乙個"abcdefg"物件——我們並不知道它在哪;把這個物件的位址給了h。

如果我們再加一句(就像題目中的5,6),const char *g = "abcdefg";我們會驚奇地發現,h跟g是

相同的——它們的位址竟然是相等的!

明白嗎?也就是說整個系統中"abcdefg"被當作乙個物件放在某處,它(編譯器)自動就建立了乙個

這樣的物件,而把這個物件的值(位址值),賦給我們的指標……

我們以為,我們是用指標const char *h = "abcdefg"; 用h,建立了乙個物件。其實不然,是系統建立

了乙個物件,並且把這個物件給我們的指標。這個物件在系統中是唯一,即使你再用const char *g = "abcdefg"; 它(編譯器)也僅僅是把這個物件("abcdefg")找出來,賦(位址)給

你的指標。

像"abcdefg"這樣的語句在我們的語法中是不允許的。因為它在這個句子裡的實際作用是建立了乙個

物件!而我們的本意不是建立這個物件,只是想讓我們的指標指向這個物件!……因此我們寫下的語句跟我們實際所做的事產生了分歧,這在c++中會引發「未定義的行為」。

不知道自己錯在哪這是最恐怖的……

但是,這只是乙個bug,明白嗎?只有在使用字串的時候才會出現這個問題。但是由於人的拓展思維,如果不加強調,很容易就和其他規律弄混淆……所以,你應該對字串有獨到的理解——僅此而已。

指標永遠是乙個位址……

以上都是思維過程,以下的是結論:

我們寫這樣的句子   

char *p = "abc";  //  ---1

似乎跟                   

char p = "abc";  //  ---2

沒什麼區別。

但是當我們要改變p的時候,這種區別便出來了。比如說我們要讓p重新「代表」"aaa"。

對於1,我們很容易寫出p = "aaa";但對於2,我們不得不寫p[0] = 'a';  p[1] = 'a'; p[2] = 'a';

p[3] = '/0';

你可能會覺得1很好。但是當真正我們在使用p的時候,又有多少時間需要去更改呢?

更為嚴重的:即便你更改了p,使p現在指向"aaa",但是原來系統中的"abc"仍然是存在的;如果你將來還要更改,那麼現在的"aaa"也永遠是存在的。——你只是更改了p指向的物件,然而卻沒有對之前的物件進行任何銷毀處理——你也沒辦法進行銷毀處理——這是乙個bug。

但是2,永遠都只有乙份副本,永遠都不會產生這樣的問題。

指標陣列,陣列指標,字串與指標

在研究指標陣列與陣列指標的時候,遇到了這個困惑,後面解答。void test02 char c 4 char p2 4 指標陣列 for int j 0 j 4 j for int i 0 i 4 i 指標陣列是陣列,即乙個陣列中,每個元素都是指標 void test05 注意這一行和最後一行的區別...

陣列 字串與指標

指標變數既可以指向變數,當然也可以指向陣列元素。就是把陣列元素的位址放入指標變數中。陣列元素的指標就是它的位址。用陣列名做函式引數時,實參和形參對應關係有四種。一是實參形參都用陣列名。二是實參形參都用指標變數。三是實參用指標變數,形參用陣列名。四是實參用陣列名,形參用指標變數。在c語言中,也有兩種方...

C 字串指標與字串陣列

在做面試100題中第21題時,發現char astr abcdefghijk 0 和char astr 有點區別,以前一直以為是一樣的,但是在該程式中採用字串指標執行一直出錯。後來在網上查查,果然發現大大的不同。分析 當你需要修改字串時,採用指標指向該字串編譯通過但是執行出錯,而採用字串陣列時不會出...