1. 程式人生 > >當指標指向一個字串

當指標指向一個字串

1.     以字串形式出現的,編譯器都會為該字串自動新增一個0作為結束符。

如在程式碼中寫"abc",那麼編譯器幫你儲存的是"abc\0"。

2.     "abc"是常量嗎?

答案是有時是、有時不是。

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

char str[] = "abc";

因為定義的是一個字元陣列,所以就相當於定義了一些空間來存放"abc",又因為字元陣列就是把字元一個一個地存放的,所以編譯器把這個語句解析為

char str[3] = {'a','b','c'};

又根據上面的總結1,所以char str[] = "abc";的最終結果是:

char str[4] = {'a','b','c','\0'};

做一下擴充套件,如果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*。

8.使用cin輸入字串的相關問題
        8.1 cin 使用空白(空格、製表符和換行符)來定字串的界
       這意味著cin在獲取字元陣列輸入時只讀取一個單詞,在讀取該單詞後,cin將該字串放到陣列中,並自動在結尾新增空字元。後一個字串將不會輸入到陣列中。

8.2 當輸入字串可能比目標陣列長時,將不能防止例如將包含30個字元的字串放到20個字元的陣列中的情況。
       9.面向行的讀取還不是面向單詞
       9.1 getline() 
       getline()讀取一行的輸入,直到到達換行符,並丟棄換行符。它有三個引數:陣列名稱、要讀取的字元長度、第三個引數為XXX
如果為20,則函式最多讀取19個字元,餘下的空間用於儲存空字元!!!注意!!!!
       9.2 get()
       get()有三個引數的版與getline()意思差不多,...,將換行符保留在輸入序列中,不通過一定的手法,get()將不能通過最後的換行符!!!!如此這樣使用:
cin.get(name,size);
cin.get();
cin.get(name2,size2);
      9.3空行和其他問題
      當getline()和get()讀取空行時怎麼辦?思考。。。
      9.4 對於一個未被初始化的字串,其內容是隨機的,也就有可能出現空字元\0!!!!要先初始化!!!
      9.5向string中輸入一行字元
       getline(cin,string);//向string中輸入一行
       cin.getline(array,size);//向普通陣列中輸入一行