目錄
二、指針能指向數組?爲啥?
1.指針與一維數組
(1)指針變量處理數組
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
int a[10],*p;
srand((int)time(0));
printf("隨機生成10個數:\n");
for(p=a;p<a+10;p++){
*p=(int)(10+90*rand()/RAND_MAX);//p本身就是地址,不用加地址符
printf("%5d",*p);
}
printf("\n");
printf("10個數中的奇數是:");
for(p=a;p<a+10;p++)
if(*p%2==0) printf("%5d",*p);
printf("\n");
printf("10個數中的偶數是:");
for(p=a;p<a+10;p++)
if(*p%2!=0) printf("%5d",*p);
return 0;
}
賦初值語句p=a必不可少,若p未賦初值,其在內存中可能任意指向一個地址,有鍵盤輸入的數據替代了該地址處存放的內容,會導致意想不到的錯誤。
(2)數組的地址
一個數組在內存中是連續存放的,數組的第一個元素地址稱爲首地址。在C語言中,數組名是該數組的首地址。
int a[10],*p;
p=a <=> p=&a[0] //表示指針變量p指向數組的首地址
數組首地址是一個地址常量,不可改變。所有,語句“a=p”和語句“a++”是非法的。
如果數組的首地址是a,且指針變量p指向該數組的首地址,即“p=a”;第 i 個元素a[i]的地址是a+i,等價於p+i;
int a[5]={1,2,3,4,5},*p=a;
double d[5]={1.1,2.2,3.3,4.4,5.5},*q=d;
(3)通過一維數組名所代表的地址存取數組元素
int a[]={1,2,3,4,5,6,7,8,9,10};
*(a+5)=50; //等價於a[5]=50
scanf("%d",&a[8]);//等價於scanf("%d",a+8)
printf("%d",*(a+5)); //打印a[5]
(4)通過指針運算符“ * ”存取數組元素
int a[]={1,2,3,4,5,6,7,8,9,10},*p=a;
*(p+5)=50;
scanf("%d",&a[8]);
printf("%d\n",*(p+5));
(5)通過帶下標的指針存取數組元素
p[i] <=> *(p+i)
int a[]={1,2,3,4,5,6,7,8,9,10},*p=a;
p[5]=50;
scanf("%d",&a[8]);
printf("%d\n",p[5]);
(6)等價規則
a[i] <=> p[i] <=> *(a+i) <=> *(p+i)
2.移動指針及兩指針相減運算(面向數組)
(1)移動指針
當指針變量指向一塊連續的存儲單元時,需要通過指針移動進行數據存取。
數據類型 *p,*q;
p=p+n;
q=q-m;
m,n爲正整數,系統自動計算出p、q在內存中位移的字節數。
p指針向高地址方向位移的字節數=sizeof(數據類型)*n;
q指針向低地址方向位移的字節數=sizeof(數據類型)*m;
【注意】
①指針變量每加一減一一次所位移的字節數等於其所指數據類型的大小,而不是簡單地把指針變量的值加1減1。
②指針變量p++爲什麼會提高程序效率?p++指針不斷指向下一個元素,p++運算比*(a+i) <=>a[i] <=>*(p+i) <=> p[i] 這4種運算要快
(2)兩指針相減運算(面向數組)
指向同一塊存儲單元的兩個指針可以進行相減運算。
指針變量只能做 移動 和 相減 運算。
#include<stdio.h>
int main(){
int a[5]={1,2,3,4,5},*p1=a,*p2;
double d[5]={1.1,2.2,3.3,4.4,5.5},*q1=d,*q2;
p1++;//從a[0]移動到a[1]
p2=p1+3; //從a[1]移動到a[4]
printf("%d\n",p1-p2);
q1++;
q2=q1+3;
printf("%d\n",q2-q1);
return 0;
}
p1和p2所指向的數據類型是整形,每位移一個元素,內存中位移4個字節;q1,q2所指向的數據類型是雙精度類型,q1和q2每位移一個元素,內存中位移8個字節。
3.指針比較
指向同一塊存儲單元的兩個指針變量可以進行關係運算(“<”、“>”、“>=”、“<=”、“==”、“!=”)。
#include<stdio.h>
int main(){
int a[]={11,22,33,44,55,66},*p=a;
printf("%3d,",(*p)++);
printf("%3d,",*p++);
printf("%3d,",*++p);
printf("%3d\n",++*p);
for(p=a;a<a+6;p++)
printf("%3d",*p);
return 0;
}
4.指向字符串的指針
(1)字符指針
一個字符指針可以指向字符串,然後通過字符指針存取字符串。
char *sp;
sp="Ok!"; //sp指向"Ok!"
C語言把字符串常量賦值給指針變量,相當於把該字符串的首地址賦值給指針變量。
當sp指向某字符串常量時,可以用sp來存取字符串,sp[i]或*(sp+i)就相當於字符串的第 i+1個字符。
#include<stdio.h>
int main(){
char s1[]="Good!",s2[15]="How are you!",*from,*to;
from=s1;
to=s2;
while(*from) *to++=*from++;
*to='\0';
printf("%s\n%s\n",s1,s2);
return 0;
}
(2)字符指針與字符數組的區別
①使用字符指針處理字符串
1.值存放的是字符串首地址
2.char *sp=“OK!”,該語句在內存中爲字符常量"OK!",分配4字節的一塊連續的存儲區存儲該字符串,在末尾加“\0”,並把字符串的首地址賦值給指針變量sp
3. char *sp;sp=“OK!” <=> char *sp = “OK!”`
4. 語句"char *sp;scanf("%s",sp);”中字符指針sp未賦初值,可能指向內存中的任意地址,輸入的字符串將代替改地址處存放內容,導致意想不到的錯誤。正確的使用方式是sp指向一字符數組“char str[300];*sp=str;scanf("%s",sp);”
5. 語句“char *sp”中sp是字符指針變量,其值可以改變。例如語句"sp=Good Morning!";sp+=5;printf("%s",sp);”將輸出"morning!"
②使用字符數組處理字符串
1.由多個元素組成,每個元素放一個字符
2.“char s[]=“OK!”,此語句定義一個數組名爲s,由4個元素組成的數組,每個元素存放相應的字符,s[0]值爲’O’,s[1]值爲’k’,s[2]值爲’!’,s[3]值爲’\0’
3.char s[50] ; s=“OK!” 是非法的,s表示數組的首地址,不可被賦值。
4.語句"char s[300];scanf(”%s",s);"中的scanf()函數的用法是正確的,由鍵盤輸入的字符將字逐字存入字符數組s中,並在輸入的字符串最後加上’\0’表示字符串結束。
5.語句“char s[300]”中s是數組名,是數組的首地址,是地址常量,其值不可改變。
(3)刪除一個字符串中所有的空格字符
#include<stdio.h>
int main(){
char s[500],*p1,*p2;
gets(s);
p1=p2=s;
while(*p1){
if(*p1==' ') p1++;
else *p2++=*p1++;
}
*p2='\0';
printf("刪除空格後的字符串是:%s\n",s);
return 0;
}