最近偶然看起了c語言,發現還十分有趣;現在起開個新坑:接下來的一系列部落格都會記錄我重新學習c語言和資料結構時的所思所感
指標變數之間賦值是需要相容的。
例如:int *a = int的位址
char *b= char的位址
void型別的指標可以做任意型別位址的賦值操作。
例如:void *p = int位址可以
p = char位址也還可以
p = char位址也還可以
例如:p++;//會出現問題
指標與陣列的關係
int a[10];
int *p = a; //初始化的時候就指向了首位址,相當於int *p = &a[0]; 也相當於int *p; p = a; 也相當於int *p; p = &a[0];
p[3] = 8; //等價於*(p + 3) = 8;該p[3]對應的是下標為3的元素。
p += 2; //指標進行運算後
p[3] = 0; //此時的p[3]對應的元素為下標為5的元素。
a += 2; //這樣寫是錯誤的,因為陣列名是乙個位址的編號,是乙個常量(該常量的解釋是:變化的常量。因為每一次執行程式時,位址編號都會發生變化,所以是變化的;又因為一旦程式執行了,那麼位址的編號就隨之確定了,不能改變了,所以就是常量了!)
p = a + 2; //因為int *p; p = a; 所以p += 2; --> p = p + 2; --> p = a + 2; //又因為a是乙個位址編號,是乙個常量,可以做右值的。
指標的運算:指標的加減不是普通整數的加減
例如:int ab[10];
short *p = ab; //乙個short型別的指標變數,指向了乙個int型的位址,但不影響p本身的型別。
p += 2; //p在記憶體中移動了4個位元組, 結果是移動到了ab[1]的位址了。
int *p1 = ab;
p1 += 2; //p在記憶體中移動了8個位元組,移動到了ab[2]的位址了。
short abc[10];
p1 = abc;
p1 += 3; //這時p1移動了12個位元組。
指標運算的時候,不要在意指標具體指向乙個什麼樣型別的位址,要在意的是指標本身是什麼樣的型別。
指標陣列:main函式的引數就是乙個典型的指標陣列(也即二級指標)。
int *a[10]; //定義了乙個陣列,名字叫a,有10個成員,每個成員的型別是int *,成員分別為a[0]、a[1]、......、a[9]。
char *b[10]; //定義了乙個陣列,名字叫b,有10個成員,每個成員的型別是char *,成員分別為b[0]、b[1]、......、b[9]。
sizeof(a) = 8 個位元組, sizeof(b) = 8 個位元組。
該定義乙個什麼型別的指標才能指向指標陣列b(char *b[10];)呢?
答:char **p = b;
p[0]是char *型別。此時p[0] = b[0]; p[1] = b[1]; ...... p[9] = b[9];
若如下這樣定義的話,就不相容:
char *p = b;
此時的p[0]是char型別。
但b[0]本身是什麼型別呢?答:b[0]是char *型別。此時 p[0] 不等於 b[0]了。
該定義乙個什麼型別的指標才能指向陣列b(char b[10];)呢?
答:char *p = b;
此時的p[0]是char型別,此時p[0] = b[0]; p[1] = b[1]; ...... p[9] = b[9];
指向指標的指標(二級指標)
int *p;
*p是什麼型別?答:int型別。
int ***p
*p是什麼型別?答:int **型別。
**p是int *型別。
***p是int型別。
指標變數作為函式引數
如果想要通過函式內部修改外部是實參的值,就需要給函式的引數傳遞實參的位址。
一維陣列名作為函式引數
一維陣列名一旦作為函式引數,c語言將陣列名解釋為一級指標變數。(由陣列名(常量)變為指標變數名(變數))
int abc(int a[10])
int abc(int a)
int abc(int *a)
如果將乙個陣列作為函式的形參進行傳遞,那麼陣列內容可以在被呼叫的函式內部進行修改,
很多時候,我們不希望這樣的事情發生,所以用到const對形參進行修飾。(儘管此種修飾方法沒有用!)
int abc(const int a[10])
指標 和 字串
在c語言中,大多數的字串(字元陣列)操作其實就是指標操作。
例如:#include
int main()
chars[20] ="hello world";
char*p = s;
p[0] ='a';
*p ='b';
printf("%s\n", s);//bello world
char*c ="hello world";
//c[0] = 'a';//編譯沒有問題,但執行會出現段錯誤。因為c指向的是乙個常量。
printf("%d\n", *c);//104
printf("%d\n", c[0]);//104
printf("%d\n", c[1]);//101
return0;
char a[100] = "hello world"; //定義乙個陣列,有100個char,同時初始化陣列成員變數的值。
char *p = a; //定義乙個char *型別的指標p,p指向char型別陣列的首元素位址。
char *s = "hello world"; //定義了乙個字串常量,s指向這個常量的首位址。
const char *s = "hello world"; //定義了乙個字串常量,s指向這個常量的首位址。(更嚴謹的寫法)
a[0] = 'a';//合法的,因為陣列a的所有成員都是變數。
s[0] = 'a';//非法的,因為s指向的是乙個常量。
char *作為函式的引數
此時函式的引數是字串。
如果函式的引數是乙個陣列,那麼函式內部是不知道這個陣列成員數量的,所以函式的形參需要額外再增加乙個引數,說明陣列成員數量。
如果函式的引數是乙個字串(本質是字元陣列),那麼就不需要增加額外引數說明字串字元數量了。
c語言指標問題
c是一門可以直接操作記憶體的語言,但這並不代表我們就可以以自己主觀的意思來操作記憶體。看下面的 includevoid pr int p,int p1 int main void pr int p,int p1 執行後結果都是12.首先,我們要明白指標的定義是乙個存放位址的變數,也就是說,它指向的位...
c語言指標問題
對於以下 段 int a int p a int q a 5 printf d q p 當sizeof int 為4時,以下說法正確的是 a.因為第三行的錯誤不能編譯 b.因為第三行的錯誤執行時崩潰 c.輸出5 d.輸出20 指標的減法實際是位址間能存放多少個指標指向物件的資料型別的值。a是int型...
c語言指標問題小結
最近使用指標的時候遇到了一些問題,在這裡做乙個簡單的總結,加深下對指標的認識。陣列和指標大部分情況下可以互換使用,但是有些時候卻是必須得區別對待,否則一不小心就會出錯。比如下面四個test例子,test1是對的,test2是錯的,指標指向乙個位址的情況,因為getuartdata 返回乙個指標位址,...