第六章
指針變量的本質是用來放地址,而一般的變量是放數值的。
1、int *p 中 *p和p的差別:簡單說*p是數值,p是地址!
*p可以當做變量來用;*的作用是取後面地址p裏面的數值
p是當作地址來使用。可以用在scanf函數中:scanf(“%d”,p);
2、*p++ 和 (*p)++的之間的差別:改錯題目中很重要!考試超級重點
*p++是 地址會變化。 口訣:取當前值,然後再移動地址!
(*p)++ 是數值會要變化。 口訣:取當前值,然後再使數值增加1。
例題:int *p,a[]={1,3,5,7,9};
p=a;
請問*p++和(*p)++的數值分別爲多少?
*p++: 這個本身的數值爲1。由於是地址會增加一,所以指針指向數值3了。
(*p)++ 這個本身的數值爲1。由於有個++表示數值會增加,指針不移動,但數值1由於自加了一次變成了2。
3、二級指針:
*p:一級指針:存放變量的地址。
**q:二級指針:存放一級指針的地址。
常考題目: int x=7;
int*p=&x,**q=p;
問你:*p爲多少?*q爲多少?**q爲多少?
7 p 7
再問你:**q=&x的寫法可以嗎?
不可以,因爲二級指針只能存放一級指針的地址。
4、三名主義:(考試的重點)
數組名:表示第一個元素的地址。數組名不可以自加,他是地址常量名。(考了很多次)
函數名:表示該函數的入口地址。
字符串常量名:表示第一個字符的地址。
5、移動指針(經常加入到考試中其他題目綜合考試)
char *s=“meikanshu”
while(*s){printf(“%c”,*s);s++;}
這個s首先會指向第一個字母m然後通過循環會一次打印出一個字符,s++是地址移動,打印了一個字母后,就會移動到下一個字母!
6、指針變量兩種初始化(一定要看懂)
方法一:int a=2,*p=&a;(定義的同時初始化)
方法二:int a=2,*p; (定義之後初始化)
p=&a;
7、傳數值和傳地址(每年必考好多題目)
void fun(int a,intb) void fun(int *a,int *b)
{ int t ; { int t ;
t=a;a=b;b=t; t=*a;*a=*b;*b=t;
} }
main() main()
{ int x=1,y=3, { int x=1,y=3,
fun(x,y); fun(&x,&y)
printf(“%d,%d”,x,y); printf(“%d,%d”,x,y);
} }
這個題目答案是1和3。 這個題目的答案就是3和1。
傳數值,fun是用變量接受,所以fun中 傳地址,fun用指針接受!這個時候fun
的交換不會影響到main中的x和y 。 中的交換,就會影響到main中的x和y。
傳數值,形參的變化不會影響實參。 傳地址形參的變化絕大多數會影響到實參!
8、函數返回值是地址,一定注意這個*號(上機考試重點)
int *fun(int*a,int *b) 可以發現函數前面有個*,這個就說明函數運算結果是地址
{ if(*a>*b)returna; return a 可以知道返回的是a地址。
else return b;
}
main()
{ int x=7,y=8,*max;
max = fun(&x,&y); 由於fun(&x,&y)的運算結果是地址,所以用max來接收。
printf(“%d,%d”,)
}
9、考試重要的話語:
指針變量是存放地址的。並且指向哪個就等價哪個,所有出現*p的地方都可以用它等價的代替。例如:int a=2,*p=&a;
*p=*p+2;
(由於*p指向變量a,所以指向哪個就等價哪個,這裏*p等價於a,可以相當於是a=a+2)
第七章
數組: 存放的類型是一致的。多個數組元素的地址是連續的。
1、一維數組的初始化:
inta[5]={1,2,3,4,5}; 合法
int a[5]={1,2,3,}; 合法
inta[]={1,2,3,4,5}; 合法,常考,後面決定前面的大小!
inta[5]={1,2,3,4,5,6};不合法,賦值的個數多餘數組的個數了
2、一維數組的定義;
int a[5];注意這個地方有一個重要考點,定義時數組的個數不是變量一定是常量。
int a[5] 合法,最正常的數組
int a[1+1] 合法,個數是常量2,是個算術表達式
int a[1/2+4] 合法,同樣是算術表達式
int x=5,int a[x]; 不合法,因爲個數是x,是個變量,非法的,
define P 5 int a[P] 合法,define 後的的P是符號常量,只是長得像變量
3、二維數組的初始化
inta[2][3]={1,2,3,4,5,6}; 合法,很標準的二維的賦值。
inta[2][3]={1,2,3,4,5, }; 合法,後面一個默認爲0。
inta[2][3]={{1,2,3,} {4,5,6}}; 合法,每行三個。
inta[2][3]={{1,2,}{3,4,5}}; 合法,第一行最後一個默認爲0。
inta[2][3]={1,2,3,4,5,6,7}; 不合法,賦值的個數多餘數組的個數了。
inta[][3]={1,2,3,4,5,6}; 不合法,不可以缺省行的個數。
inta[2][]={1,2,3,4,5,6}; 合法,可以缺省列的個數。
補充:
1)一維數組的重要概念:
對a[10]這個數組的討論。
1、a表示數組名,是第一個元素的地址,也就是元素a[0]的地址。(等價於&a)
2、a是地址常量,所以只要出現a++,或者是a=a+2賦值的都是錯誤的。
3、a是一維數組名,所以它是列指針,也就是說a+1是跳一列。
對a[3][3]的討論。
1、a表示數組名,是第一個元素的地址,也就是元素a[0][0]的地址。
2、a是地址常量,所以只要出現a++,或者是a=a+2賦值的都是錯誤的。
3、a是二維數組名,所以它是行指針,也就是說a+1是跳一行。
4、a[0]、a[1]、a[2]也都是地址常量,不可以對它進行賦值操作,同時它們都是列指針,a[0]+1,a[1]+1,a[2]+1都是跳一列。
5、注意a和a[0] 、a[1]、a[2]是不同的,它們的基類型是不同的。前者是一行元素,後三者是一列元素。
2) 二維數組做題目的技巧:
如果有a[3][3]={1,2,3,4,5,6,7,8,9}這樣的題目。
步驟一:把他們寫成: 第一列 第二列 第三列
a[0]à 1 2 3 ->第一行
a[1]à 4 5 6 —>第二行
a[2]à 7 8 9 ->第三行
步驟二:這樣作題目間很簡單:
*(a[0]+1)我們就知道是第一行的第一個元素往後面跳一列,那麼這裏就是a[0][1]元素,所以是1。
*(a[1]+2)我們就知道是第二行的第一個元素往後面跳二列。那麼這裏就是a[1][2]元素,所以是6。
一定記住:只要是二維數組的題目,一定是寫成如上的格式,再去做題目,這樣會比較簡單。
3) 數組的初始化,一維和二維的,一維可以不寫,二維第二個一定要寫
int a[]={1,2} 合法。 int a[][4]={2,3,4}合法。 但inta[4][]={2,3,4}非法。
4) 二維數組中的行指針
int a[1][2];
其中a現在就是一個行指針,a+1跳一行數組元素。 搭配(*)p[2]指針
a[0],a[1]現在就是一個列指針。a[0]+1 跳一個數組元素。搭配*p[2]指針數組使用
5) 還有記住脫衣服法則:超級無敵重要
a[2] 變成 *(a+2) a[2][3]變成 *(a+2)[3]再可以變成 *(*(a+2)+3)
這個思想很重要!