C語言中的指標和字串

2021-06-28 02:11:39 字數 3419 閱讀 9095

務必理解指標與記憶體模型,不要死記硬背。

c語言中的字串一般是char *型別的,這是怎樣存在記憶體中的呢?

cchar *s = "nihao";

| s:400 |

|---|---|---|---|

|'n'|'i'|'h'|'a'|'o'| 0 |

|---|---|---|---|---|---|

|400|401|402|403|404|405|

如是上圖,假設字母a處於記憶體的第400號格仔,那麼後面幾個字母也是緊跟著的。

變數s本身並沒有儲存字串,而存的是字串的首位址400。也即,s指向這個字串。

為什麼沒有專門乙個字串的型別而是要靠乙個指標指向它呢?因為字串的長度是不固定的,所以乙個字串還包含著長度資訊,基本型別是無法處理資料結構的。

我們都知道字串是以0結尾的,而且這個更像是一種約定,c編譯器本身並沒有對此做任何保證。比如這樣

cchar s[3] = "asd";

puts(s); /* prints "asd" or something longer */

這樣做是危險的,因為s只有3個格仔,字串結尾的0並沒有放進去。如果在它後面的記憶體格仔並不是0,那這個字串就跟我們預期的不一樣了。

"abc"[0] = 'z'; /* wrong */

char *s = "abc";

s[0] = 'z'; /* wrong */

char s[5] = "abc";

s[0] = 'z' /* right */

當指標s指向的是字串常量(即直接寫在程式裡面的字串時),要注意它是不可寫的

為啥用陣列就沒問題呢,因為陣列的初始化和指標有點區別

char s[5] = "abc";

/* 相當於 */

char s[5];

strcpy(s, "abc");

如果擔心自己會不小心寫錯,可以加上const關鍵字,這樣編譯的時候就會報錯

這是乙個好習慣,接下來的示例程式中都會這麼寫。

const char *s = "abc";

s[0] = 'z'; /* causes a compiling error instead of runtime error */

/* wrong */

char *s;

char c = s[0];

上面的程式編譯是能過的(可能有warning),但執行是一定會出錯的,因為編譯器並不知道s指向哪些格仔。

/* right */

const char *s = "nihao";

char c = s[0];

這樣,其實是隱式的分配了6個格仔(包括字串結尾的0),並讓s指向它們

/* right */

char s[6];

char c = s[0];

/* right */

char s[6] = "nihao";

char c = s[0];

陣列其實跟指標沒什麼區別,主要的區別是它在宣告的時候就分配好了格仔(方括號裡的6就是告訴編譯器給我6個格仔),而且陣列不能改變它的指向(也不能再要更多的格仔)。

const char *s = "abcd";

const char *t = "abcd";

/* wrong */

if (s == t)

/* right */

if (!strcmp(s, t))

因為s和t都沒有存字串的內容,它們存的是字串的位址,如果用==比較,比較的是兩個字串的位址是否相同。我們希望比較的是內容是否相同。

請使用c語言庫函式中的strcmp比較字串是否相等

/* tries to copy a string */

char s[5] = "abcd";

char *t = s;

t[3] = 'z';

puts(s); /* puts "abcz" */

上面這種做法讓t和s指向同一字串,修改t指向的內容,會發現s指向的內容也被修改了。這種做法沒有錯,經常會用到,但不一定是你想要的。

/* wrong */

char *s = "abcd";

char *t; /* not initialized */

strcpy(t, s);

/* right */

char *s = "abcd";

char t[10] = ; /* or char *t = (char *) malloc(5*sizeof(char)); */

strcpy(t, s);

使用strcpy複製字串的內容而不是指標,但也要注意初始化t這個指標

int,float之類的很簡單直接return就好

但現在我想寫乙個函式,它能夠得到乙個字串

/* no problem, but meaningless */

const char *f()

/* wrong */

char *f()

/* result correct but not good */

char *f()

第一種情況就不說了,返回乙個字串常量並沒有問題因為它不可修改,但是不可修改也就沒什麼意義了。

第二種情況是完全錯誤的,返回乙個區域性的陣列。這個陣列的記憶體會在函式呼叫完後被收回,因此返回的指標指向的時候沒有意義的地方。現代編譯器一般都會對這個有warning。

第三種情況是返回malloc的指標。這種情況你可以得到正確的答案,但是不推薦,呼叫這個函式的人很有可能

一旦沒有注意,多次呼叫這個函式,結果就是記憶體溢位,這樣的錯誤還非常不好排查,所以不推薦

正確的做法是把分配記憶體這種事情放在函式外面做,正如strcpy一樣

char *strcpy(char *dest, const char *src)

return dest;

}

注意這裡返回了char *但其實返回的正是原本傳進來的dest,這裡只是為了方便而已。

呼叫方法在上面也提到過。

在c語言中 C語言中的指標和字串

之前我們說過關於字元的一些內容,字元的原理,歸根到底就是將我們常用的一些字元根據編號整理成一張統一的表,每個字元對應著這個表裡面的乙個數值,這一過程就是字元的編碼。然而大多數時候我們根本就不會使用單個字元,比如計算機上面要輸出一句句子 hello world 這個句子裡面就是由多個字元所組成的,分別...

C語言中字元陣列和字串指標分析

寫下面的測試程式 include int main int argc,char argv 執行後螢幕上得到如下結果 其實看到結果估計很多東西就好明白了,先看看前三個輸出也就是關於變數day的,在 char day 15 abcdefghijklmn 這個語句執行的時候,系統就分配了一段長15的記憶體...

C語言中字元陣列和字串指標分析

這幾天搞unix上的c程式,裡面用到了很多字元陣列和字串指標,我記得在學完c語言後相當一段時間裡,對指標這個東西還是模模糊糊,後來工作也沒怎麼用到過c,雖然網上這類的文章也有很多,還是決定自己在這做個小總結,也算加深下自己的印象,寫了下面的測試程式 01 include 02 03intmain i...