C語言之指標與陣列總結

2022-03-22 01:57:44 字數 3858 閱讀 3315

和指標相關的問題

口訣1

1.位址變數得位址,得誰位址指向誰

和指標相關的問題要畫圖: 內容變數畫房子,指標畫箭頭

---->口

一、"&" 取位址運算子,通過&運算子可以取出普通變數的位址;

二、"*"  有兩種意義:

1.  為指標標誌: 是否為指標標誌主要看前面是否有型別,此處有乙個int

2.  為指標運算子:

在等號右面為取值。*可以取出指標變數所指向的普通變數的值。

在等號左面為賦值。*可以將指標變數所指向的普通變數的值,修改為其他。

口訣2有* 為內容值,不是讀就是寫。等號左面為賦值, 其餘都為取值。

3.  為乘法運算子。當且僅當左右的都為變數時。略。

如int a, b =20, c=30, d=40, *p; (正確,此處的*為指標標誌,只起到定義的左右,沒有取值和賦值的作用。是否為指標標誌主要看前面是否有型別,此處最前面有乙個int)

p=&d; (正確,p指向d的位址)

a=*p;  (正確,此處的*為取值。最後結果a的值變為了d的值40)

*p =c; (正確,此處的*為賦值。最後結果d的值變為了c的值30)

*p =&b; (執行錯誤,左邊為內容值,右邊為位址,不等價)

和指標相關的等價表示式

若指標變數p指向變數a,即將變數a的位址賦給了指標變數p.

如:int a=20, int *p=&a;

則有如下結果:

a、*p <=> a

b、 p <=> &a

c、 &*p <=> &a <=> p

d、*&a <=> *p <=> a

e、 (*p)++  a++ 

(*p)--  a--    

++(*p)  ++a   ++*p   

--(*p)  --a   --*p

可以看出 * 和 & 是互逆的兩個運算子

所有的指標變數在記憶體中分配的位元組數相同 sizeof(指標) 永遠是 兩個位元組, 不管指標定義時是 int *, float * 還是 double * . 詳細如下

int *p1;   則 p1以後必須指向int 型別的變數。   但指標本身的長度,sizeof(p1) 為2個位元組(2*8bit -16bit)

float *p2;   則 p2以後必須指向float 型別的變數。   但指標本身的長度,sizeof(p2) 為2個位元組(2*8bit -16bit)

double *p3;   則 p3以後必須指向double 型別的變數。   但指標本身的長度,sizeof(p3) 為2個位元組(2*8bit -16bit)

四道例題:

例子1.

void fun (int *x , int *y)

main()

結果2, 1

4, 3

注意main在呼叫fun函式時, y 和x故意寫顛倒了。

例子2. 

#include

void swap(int *p1, int *p2)

main()

如果在控制台輸入2 和 5

則輸出結果為 

5, 2

原因: 在呼叫swap函式時使用了職稱,所以在swap函式內部對p1,p2 所引用的內容值的修改,會影響外面的a和b的值。

例子3:

#include

void swap(int *p1, int *p2)

main()

和2不同, swap函式中的temp為指標,temp=p1使得temp指向了2,p1=p2使得p1指向了5,p2=temp使得p2指向了5.

但最後的列印結果仍為

2,5原因是:雖然main中呼叫swap函式時使用了指標傳遞,但swap函式中的所有操作都是:將指標本身的修改,而沒有再次使用*操作符來修改「指標指向的內容值」

口訣3:沒有*的指標操作為位址,位址的賦值意味著改指向。

例子4:

#include

void swap(int *p1, int *p2)

main()

和2很像。但唯一不同是,temp定義為指標而不是普通變數。看上去似乎應該和2的輸出結果一樣,仍為

2,5 。

但實際執行時編譯器會報錯:非法的記憶體寫入。

原因是:temp為野指標,並沒有預訂指向**。如果指向系統區,則可能導致作業系統宕機或崩潰。

如果temp在定義後,馬上給乙個初始值,就不會有問題了。

指標、陣列的等價符號

若將陣列作為形參,則將陣列名作為指標變數來處理。

int fun(int a[10]) <=> int fun(int *a) <=> int fun(int a)

可以看出,口訣4:  &與*互逆。 *與等價, &與互逆

例子5:

int s[10], a, b;

in d[3][6];

int *p;

p=&a; //p 指向了整數a

p = &s[2]; //p指向了s陣列的第二個元素

p= &d[2][4];////p指向了d陣列的第二行、第四列的元素。

所以,以上的語句都是對的。

上面的例子:

1. 定義了乙個int s[10];   則 s等同於 &s[0].   即,看到乙個陣列,就馬上聯想到他代表的是陣列第乙個元素的位址。

在c語言中規定,資料名代表陣列的首位址,並且是乙個位址常量

2. 另外,如果定義了乙個指標 int *ppp = s;  則   ppp 定價於s,  同時等價於 &s[0]。

指標的加減:

例子6:

float a[10]; float *p;

p=&a[4]; 則p-3指向?

先畫圖:

a[0] | a[1] | a[2] | a[3] | a[4] | ...

p的初始位置指向了 a[4],  則 p-3 為向前3個,指向了 a[1]

口訣5:  指標的加減是向前或向後移動了n個元素

int a[n], *p=a;

則有:存在等價表示式:

p+i <=> a+i <=> &a[i]  代表的是第i個元素的位址

元素四等價:

存在等價表示式:

1.   *(p+i) <=> *(a+i) <=> a[i]   代表的是第i個元素的值

2.  另外,還有 p[i] <=> a[i] 。 p[i] 的用法不多見,但無任何錯誤,代表的也是第i個元素的值。原因是p和a完全等價。

a) *(p+i) <=> *(a+i) <=> a[i] <=> p[i]

b) p++ <=> ++p <=>  p+=1 <=>  p=p+1

c) p-- <=>  --p  <=>  p-=1  <=>  p=p-1

d) *p++  <=>   *(p++)

說明:* 與 ++ 的運算優先順序一樣,所以按照從右到左的結合原則,先執行++,後執行*

++在p的後面,為執行後再加。即先把p的值取出,指標再加1.

e) *++p  <=>  *(++p)

++在p的前面,為先加再執行。即先把指標加1, 再把移動後的p所指向的值取出,

f) (*p)++ <=>   ++(*p)  <=>   ++*p

將p的內容自增

g) (*p)--  <=>  --(*p)  <=>   --*p

將p的內容自減

c語言之指標與陣列

考慮該例子 int calendar 12 31 該語句宣告了calendar是乙個陣列,該陣列擁有12個陣列元素,其中每個元素都是乙個擁有31個整型元素的陣列 而不是反過來理解 因此,sizeof calendar 的值是12 31 372與sizeof int 的乘積。如果calendar不是用...

C語言之指標與陣列

前言 訪問陣列元素既可以使用陣列名加下標的方法,也可以使用指標的方法。但使用指標的方法可以使 更緊湊 更靈活 更高效。一 幾個概念而陣列名代表陣列的起始位址,即陣列的指標。說明 二 指標訪問一維陣列 1 利用指標名構造指標表示式 例如 定義整型陣列a,int a 6 2 利用指標變數訪問陣列 三 指...

C語言之辨別指標陣列與陣列指標

我們先來說一下指標陣列,顧名思義,這是乙個存放指標型別的陣列 從定義上來看 int p 3 沒有括號括起來它還是陣列這裡我還是寫乙個程式來理解一下 include intmain for int i 0 i 3 i return0 程式執行的結果 1 23指向指標的陣列 又稱行指標 如何定義 int...