指標與變數和一維陣列
1. 山雨欲來風滿樓(指標要來了)
您(假如是穎穎)現在處於7#216教室,如果您的心上人(假如是彬彬)來看望您,假設有兩種情況存在:
(1)他只知道您的名字
(2)他知道您當前所處的位置
哪一種情況下,他找到您的效率最高?
我們現在要去某個地方(例如七十二潭),常常先開啟百度地圖,規劃好路線,其實這個路線恰恰就是定位目的地所處的位置。如果僅僅知道目的地,則需要費一番功夫才能到達。
大一來報到時,給你說7號樓,你也找不到呀,但如果給你提供了具體路線,你就可以輕易到達。
先來看一個程式,執行一下看看結果。
#include<stdio.h> int main() { int a=4; printf("%d\n",a); printf("%x\n",&a); return 0; }
我們知道,預計int a=4; 定義了一個整型變數a,系統會在記憶體中為a開闢空間,則該空間的名稱為a,4為該空間中儲存的資料。從執行結果可知,給a開闢的空間的首地址為12ff44。根據前面的分析,我們想到:可以根據變數名a來找到a,顯然也可以根據地址12ff44來找到a呀!那麼,如何根據地址來找到a呢?人是有智慧的,可以根據地址去找尋。但計算機該怎麼辦呢?
2. 指標駕到,速來接駕
針對上述程式,採用指標如下:
#include<stdio.h> int main() { int a=4; int *p; p=&a; printf("%d\n",a); printf("%d\n",*p); //*p是對指標變數p所指向的變數進行引用 *p=9; printf("%d\n",a); return 0; }
因為a為int,想通過a的地址來訪問a,則需要定義一個指標變數p,int* p;(p為變數名,*告訴編譯器p為指標變數,int則說明p指向的空間裡面存放的是int型別的資料。
這裡所說的指向是一個形象化的描述,因為p的空間中存放的是a的地址,根據該地址可以找到a,所以形象地認為p指向了變數a的空間。
需要注意:(1)指標和指標變數的區別:指標是地址,而指標變數是存放地址的變數。指標變數也有自己的地址。
#include<stdio.h> int main() { int a=4; int *p; p=&a; printf("%x\n",&a); //變數a在記憶體中的地址 printf("%x\n",p); //變數p空間中存放的資料 printf("%x\n",&p); //變數p在記憶體中的地址 return 0; }
也可以採用格式%p輸出地址值。可以根據sizeof§看看指標變數所佔的位元組數。
思考:
double a=3.5;
double* p=&a;//把a的地址賦值給指標變數p
p=a;//這條語句合法嗎?
3. 指標性格開朗,廣泛交友
3.1指標與變數
1. 通過指標變數給所指向的變數賦值
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q;
p=&i;
q=&j;
printf("i=%d,j=%d\n",i,j);
printf("*p=%d,*q=%d\n",*p,*q);
scanf("%d%d",p,q);
printf("i=%d,j=%d\n",i,j);
printf("*p=%d,*q=%d\n",*p,*q);
return 0;
}
通過scanf("%d%d",p,q);給i和j輸入了新的資料。
2. 可以改變指標變數的指向
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q,*m;
p=&i;
q=&j;
printf("%d,%d\n",*p,*q);
m=p;p=q;q=m;
printf("%d,%d\n",*p,*q);
return 0;
}
通過三條語句m=p; p=q; q=m;改變了p和q的指向。
3. 通過指標變數來改變其所指向的變數的值
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q,m;
p=&i;
q=&j;
m=*p;*p=*q;*q=m;
printf("%d,%d\n",*p,*q);
return 0;
}
通過三條語句m=*p;*p=*q;*q=m;改變了p和q所指向空間的資料。
你是否想起了函式那一章的swap()交換函式???
3.2指標與一維陣列
針對求最值問題,講述指標對一維陣列的三種操作形式。
1. 第一種形式,指標變數法:*指標變數
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
max=min=a[0];
for(p=a+1;p<a+10;p++)
{
if(*p>max)//if(a[i]>max)
max=*p;//max=a[i];
if(*p<min)//if(a[i]<min)
min=*p;//min=a[i]
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}
該形式,需要不斷改變指標變數p的指向。
想一下,既然陣列名a表示陣列的首地址,a+1表示a[1]元素的地址,能否像指標變數p那樣,對a執行a++操作呢????
2. 第二種形式,首地址法:*(首地址+偏移量)
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
max=min=a[0];
for(p=a,i=1;i<10;i++)
{
if(*(p+i)>max)//if(a[i]>max)
max=*(p+i);//max=a[i];
if(*(p+i)<min)//if(a[i]<min)
min=*(p+i);//min=a[i]
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}
該形式,並未改變指標變數p的指向,語句p=a;使得p指向陣列a的首地址,採用p+i的方法來表示a[i]的首地址,進而通過*(p+i)獲得a[i]元素的值。
3. 第三種形式,下標法:陣列名[下標]
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
p=a;
max=min=p[0];
for(i=1;i<10;i++)
{
if(p[i]>max)
max=p[i];
if(p[i]<min)
min=p[i];
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}