1. 程式人生 > >指標與變數和一維陣列

指標與變數和一維陣列

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;
}

我們知道,a[i]可以表示陣列a中下標為i的元素,當把p=a;之後,也可以通過p[i]的形式來描述a[i]元素。