字元陣列和字元指標的區別分析

2022-04-01 14:18:58 字數 4048 閱讀 4295

1.字元指標可以指向乙個字串。

我們可以用字串常量對字元指標進行初始化。例如,有說明語句:

char *str = "this is a string.";

是對字元指標進行初始化。此時,字元指標指向的是乙個字串常量的首位址,即指向字串的首位址。

這裡要注意字元指標與字元陣列之間的區別。例如,有說明語句:

char string[ ]="this is a string.";

此時,string是字元陣列,它存放了乙個字串。

字元指標str與字元陣列string的區別是:str是乙個變數,可以改變str使它指向不同的字串,但不能改變str所指的字串常量。string是乙個陣列,可以改變陣列中儲存的內容。

2.例項:

char *str, *str1="this is another string.";

char string[100]="this is a string.";

則在程式中,可以使用如下語句:

str++; /* 指標str加1 */

str = "this is a new string."; /* 使指標指向新的字串常量*/

str = str1; /* 改變指標str的指向*/

strcpy( string, "this is a new string.") /* 改變字串的的內容*/

strcat( string, str) /* 進行串連線操作*/

在程式中,不能進行如下操作:

string++; /* 不能對陣列名進行++運算*/

string = "this is a new string."; /* 錯誤的串操作*/

string = str1; /* 對陣列名不能進行賦值*/

strcat(str, "this is a new string.") /* 不能在str的後面進行串連線*/

strcpy(str, string) /* 不能向str進行串複製*/

3.其它說明:

1) 以字串形式出現的,編譯器都會為該字串自動新增乙個0作為結束符,如在**中寫:"abc",那麼編譯器幫你儲存的是"abc\0"

2) "abc"是常量嗎?答案是有時是,有時不是。

不是常量的情況:"abc"作為字元陣列初始值的時候就不是,如

char str = "abc";

因為定義的是乙個字元陣列,所以就相當於定義了一些空間來存放"abc",而又因為字元陣列就是把字元乙個乙個地存放的,所以編譯器把這個語句解析為char str[3] = ;又根據上面的總結1,所以char str = "abc";的最終結果是char str[4] = ;

做一下擴充套件,如果char str = "abc";是在函式內部寫的話,那麼這裡的"abc\0"因為不是常量,所以應該被放在棧上。

是常量的情況:把"abc"賦給乙個字元指標變數時,如

char* ptr = "abc";

因為定義的是乙個普通指標,並沒有定義空間來存放"abc",所以編譯器得幫我們找地方來放"abc",顯然,把這裡的"abc"當成常量並把它放到程式的常量區是編譯器最合適的選擇。所以儘管ptr的型別不是const char*,並且ptr[0] = 'x';也能編譯通過,但是執行ptr[0] = 'x';就會發生執行時異常,因為這個語句試圖去修改程式常量區中的東西。

記得哪本書中曾經說過char* ptr = "abc";這種寫法原來在c++標準中是不允許的,但是因為這種寫法在c中實在是太多了,為了相容c,不允許也得允許。雖然允許,

但是建議的寫法應該是const char* ptr = "abc";這樣如果後面寫ptr[0] = 'x'的話編譯器就不會讓它編譯通過,也就避免了上面說的執行時異常。

又擴充套件一下,如果char* ptr = "abc";寫在函式體內,那麼雖然這裡的"abc\0"被

放在常量區中,但是ptr本身只是乙個普通的指標變數,所以ptr是被放在棧上的, 只不過是它所指向的東西被放在常量區罷了。

3) 陣列的型別是由該陣列所存放的東西的型別以及陣列本身的大小決定的。如char s1[3]和char s2[4],s1的型別就是char[3],s2的型別就是char[4],

也就是說儘管s1和s2都是字元陣列,但兩者的型別卻是不同的。

4) 字串常量的型別可以理解為相應字元常量陣列的型別,

如"abcdef"的型別就可以看成是const char[7]

5) sizeof是用來求型別的位元組數的。如int a;那麼無論sizeof(int)或者是sizeof(a)都是等於4,因為sizeof(a)其實就是sizeof(type of a)

6) 對於函式引數列表中的以陣列型別書寫的形式引數,編譯器把其解釋為普通的指標型別,如對於void func(char sa[100],int ia[20],char *p)

則sa的型別為char*,ia的型別為int*,p的型別為char*

7)根據上面的總結,來實戰一下:

對於char str = "abcdef";就有sizeof(str) == 7,因為str的型別是char[7],

也有sizeof("abcdef") == 7,因為"abcdef"的型別是const char[7]。

對於char *ptr = "abcdef";就有sizeof(ptr) == 4,因為ptr的型別是char*。

對於char str2[10] = "abcdef";就有sizeof(str2) == 10,因為str2的型別是char[10]。

對於void func(char sa[100],int ia[20],char *p);

就有sizeof(sa) == sizeof(ia) == sizeof(p) == 4,

因為sa的型別是char*,ia的型別是int*,p的型別是char*。

4.區別:

(1)字元陣列由若干個元素組成,每個元素中存放字串的乙個字元,而字元指標變數中存放的是字串的首位址。

(2)初始化方式不同。對字元陣列初始化要用static儲存類別,在編譯時進行。而對字元指標變數初始化不必加static,在實際執行時進行。

(3)賦值方式不同。對字元陣列不能整體賦值,只能轉化成份量,對單個元素進行。而字元指標變數賦值可整體進行。

例如:

char s[10];

s= \"c++\";/*錯,s是常量,怎能被賦值*/

(4)在定義乙個字元陣列時,編譯時即已分配記憶體單元,有確定的位址。而定義乙個字元指標變數時,給指標變數分配記憶體單元,但該指標變數具體指向哪個字串,並不知道,即指標變數存放的位址不確定。例如:

char a[10];

char *p;

scanf(\"%s\",s);/*正確*/

scanf(\"%s\",p);/*非常危險,p的值動態*/

(5)字元指標變數的值可以改變,字元陣列名是乙個常量,不能改變。例如,有簡單程式:

main()

執行結果:man

字元陣列和字元指標的區別

在c語言中,對字串的操作主要有兩種方式,一是使用字元陣列,char str 二是使用字元指標。那麼二者有什麼區別呢?下面將分述二者的使用,最後進行比較。一 字元陣列 使用char str定義乙個字元陣列str,中括號內可以寫上數字表示陣列大小,也可以不寫。如果不寫數字,則必須為字元陣列提供初始值,以...

字元陣列和字元指標用法的區別

字元指標 char p,只可接收已知的字串字面量 字元陣列 char a 100 可接收已知或未知的字串。原理 字元指標只能儲存乙個字元型別的位址,而字串字面量表示式的返回值是 首元素首位址,所以字元指標可以獲得該首位址,並且可以通過指標讀取該字串,但不能修改,因為字串字面量都儲存在唯讀記憶體區域內...

指標與陣列 字元指標,字串和字元陣列的區別

指標和陣列是不相等的,把乙個陣列名作為乙個引數傳遞給函式時陣列名就是指向第乙個元素的指標,在大多數表示式中 陣列名的值是指向第乙個元素的指標 有兩個例外,乙個是sizeof返回的是整個陣列 的位元組數,乙個是 操作符返回 的是乙個指向陣列的指標 但不代表 兩者等價。int a 3 int b 宣告乙...