和指針相關的問題口訣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) {
printf("%d, %d", *x, *y) ;
*x = 3;
*y = 4;
}
main()
{
int x = 1, y = 2
fun(&y, &x);
printf("%d, %d", x, y);
}
結果
2, 1
4, 3
注意main在調用fun函數時, y 和x故意寫顛倒了。
?--------------------------------------------------------------
例子2.?
#include <stdio.h>
void swap(int *p1, int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
如果在控制臺輸入??2 和 5
則輸出結果為?
5, 2
原因: 在調用swap函數時使用了職稱,所以在swap函數內部對p1,p2 所引用的內容值的修改,會影響外面的a和b的值。
?--------------------------------------------------------------
例子3:
#include <stdio.h>
void swap(int *p1, int *p2)
{
int *temp;
temp = p1;
p1 = p2;
p2 = temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
和2不同, swap函數中的temp為指針,temp=p1使得temp指向了2,p1=p2使得p1指向了5,p2=temp使得p2指向了5.
但最后的打印結果仍為
2,5
原因是:雖然main中調用swap函數時使用了指針傳遞,但swap函數中的所有操作都是:將指針本身的修改,而沒有再次使用*操作符來修改“指針指向的內容值”
口訣3:沒有*的指針操作為地址,地址的賦值意味著改指向。
---------------------------------------------------------------------
例子4:
#include <stdio.h>
void swap(int *p1, int *p2)
{
int *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
和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]。
?---------------------------------------------------------------------
指針的加減:
當指針變量指向數組中的某一個地址時,指針變量加1后指向數組的下一個元素,
指針變量減1時指向數組的前一個元素。
?例子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的內容自減
?