初識指針


初識指針

一、什么是指針?

在了解指針之前先要先弄清楚地址的概念。

如果在程序中定義了一個變量,在對程序進行編譯時,系統就會給這個變量分配內存單元。編譯系統根據程序中定義的變量類型,分配一定長度的空間。

例如:整型變量分配4個字節,字符型分配1個字節,單精度分配4個字節等。內存區的每一個字節有一個編號,這就是“地址編號”,它就相當於旅館中的房間號,每一個房間都可以看作一塊內存區域,都可以用來存放東西,我們給每個房間都編一個房間門牌號,用於更好的區分每一個房間,內存中也是一樣的,整個內存由很多個字節組成,每個字節都有其對應的“房間號”,這就是“地址”了。通過這個“房間號”就可以找到其對應的“房間”,然后就可以從房間里取東西,或者把東西放進房間里了。

理解了地址的概念之后,那所謂的指針,就是內存地址,也就是地址的編號,可以把“指針指向地址”理解成“用小本本把房間號記下來”,那這個小本本就相當於一個用於記房間號的指針了,一個變量的地址稱為此變量的“指針”。

二、指針常量與指針變量

1、指針常量

​ 之前有了解過不同數據類型的變量所占內存字節數的這個概念,那么系統在編譯時給一個變量分配的內存地址就稱為此變量的“指針”,這個指針的指向是無法改變的,所以又稱為指針常量,數組的地址也是指針常量(也稱為地址常量)。

int a = 10;
//&a = 10000;	//&a取變量a的地址,是一個地址常量,不能夠改變它的位置

scanf("%d",&a);		//輸入222
printf("a=%d\t &a=%p/n",a,&a);	//輸出地址

2、指針變量

(1)指針變量的概念

如果有一個變量專門用來存放另一個變量的地址,則稱這個變量為“指針變量”,也就是說C語言中有一類變量是專門用來存儲(指向)地址的,我們將它稱為“指針變量”,指針變量的中存儲的地址可以被改變,也就是可以改變指針變量的指向,就好比一張紙或一個小本本,寫着一個房間的房間號,那把這個房間的房間號擦掉,寫上另一個房間的房間號也是可以的,這就是指針變量和指針常量最大的區別所在了,可以改變指針變量的指向。

//定義指針變量格式:數據類型 *變量名; 
int* p;

(2)指針變量的定義

定義指針變量的一般格式:

類型名* 指針變量名;

int a= 10;
int* p;	//定義了一個整型指針變量p,可以用於指向整型數據的地址(里面保存的是整型變量的地址)
p = &a;	//將整型變量a的地址賦值給整型指針變量p,整型指針p指向了整型變量a的地址。

int*p,*q;
char* p1,*q1;
double *p2,*q2;

/* 注意:左端的int、char等是在定義指針變量時必須指定的“基類型”。指針變量的基類型用來規定此指針變量可以指向的變量的類型。如:上面定義的*p和*q只能用於指向int整型變量的地址,p2和q2只能用於指向double雙精度類型變量的地址。 */
char *q;
int *p;
printf("%d %d\n",sizeof(p),sizeof(q));	//都輸出為4,指針變量所占內存大小一般是占4個字節

(3) 指針變量的引用:

int* p;	//定義了一個整型指針變量p,這里的'*'是指針變量定義符
*p;	//*p解引用,這里'*'是解引用符號
int a=10;
int *p;
p = &a;
printf("*&a=%d");	//對a的地址進行解引用,輸出為10,。
printf("&p=%p ");	//輸出為指針變量p的地址(p自己的地址,不是存儲其他變量地址的地址)
與指針和地址相關運算符:’*’(指針運算符)和’&’(取地址運算符)  //區別對待位運算符&
//例如:int a,*p;	p=&a;	*p=10;
//在引用指針變量時,有以下幾種情況:
//1、給指針變量賦值
如:int a = 10,b=20;
int *p=&a;
//定義一個整型指針變量p,初始化p的值為a的地址,也就是p指向a地址

/*解引用:*/
*p=30;	//通過指針變量p引用a變量,改變a的值為30
//這里的’*’為解引用符號,*p引用指針變量p所指向地址中對應的值
scanf(“%d”,p);	//scanf通過指針變量p給變量a賦值
printf(“%d\n”,*p);	//通過指針變量p輸出變量a的值
*p=b;	//將b的值放入指針變量p所指向的內存地址中(a的地址單元中)
p=&b;	//改變指針p的指向,指針p不再指向a的地址了,而是指向b的地址
printf(“%d\n”,*p);	//輸出變量b的值

//輸出內存地址編號
printf(“%p\n”,p);	//以十六進制的格式輸出指針變量p所指向地址的內存地址編號
printf(“%d\n”,&a);	//以十進制的格式輸出變量a所在的內存地址編號
printf(“%o\n”,&b);	//以八進制的格式輸出變量b所在的內存地址編號
printf(“%p\n”,&p);	//以十六進制的格式輸出指針變量p所在的內存地址編號

三、指針變量作為函數參數

函數的參數不僅可以是整型、浮點型、字符型的數據,還可以是指針類型。它的作用是將一個變量的地址傳遞到另一個函數中。

1、函數參數為指針類型的函數:

//1、函數參數為指針類型的函數:
void fun1(int x,int y)
{//這里定義了一個普通函數fun1
	printf(“x=%d\ty=%d\n”,x++,y++);
}

void fun2(int *x,int *y)
{//這里定義了一個形參為整型指針類型函數fun2,其形參為指針類型的變量
	printf(“x=%d\ty=%d\n”,(*x)++,(*y)++);	//注意*和++的優先級,++的優先級高
	
    //注意:和printf(“x=%d\ty=%d\n”,x++,y++);的區別,也就是沒有*和有*的區別
    //沒有*就是指針的偏移,指針本身移動
}

int main()
{
	int a=10,b=20,*p,*q;
	fun2(&a,&b);	//這里調用函數fun時,所傳遞的實參必須是地址
	printf(“a=%d\tb=%d\n”,a,b);	//輸出的a和b的值為11,21
	p=&a;	//使用整型指針變量p指向整型變量a的地址
	q=&b;	//使用整型指針變量q指向整型變量b的地址
	fun2(p,q);	//這里使用指針變量p和q作為實參傳遞
	printf(“*p=%d\t*q=%d\n”,*p,*q);
return 0;
}

2、指針函數

//返回值為指針類型的函數稱為“指針函數”:
int *fun3(int *x)	//這是一個指針函數,返回值類型為整型int指針類型
{//int* x = &a;
    
	++*x;	
	return x;	//返回指針變量x所指向的內存地址

}


//調用
int a=10;
int* p;
p=fun3(&a);
printf("a=%d\t");	//輸出11;


int *fun4()
{
    int a=10;	//局部變量:出了作用域,內存揮被釋放
    //如果加static,出了作用域,其內存不會被釋放,但是只能在作用域范圍內使用
	return &a;	//返回a內存地址
    //注意:不允許返回局部變量的地址

}

int* p;
p=fun4();	//p=&a;使用了非法空間

四、通過指針引用數組

1、數組元素的指針

數組元素的地址表示:

如:int a[10] = {0,1,2,3,4,5,6,7,8,9},*p;

&a[0]; //引用數組元素a[0]地址的表示方法

2、指針指向數組元素

p=&a[1];	//指針變量p指向數組元素a[1]的地址

3、指針指向的移動(指針的偏移)

int a[10] = {0,1,2,3,4,5,6,7,8,9},*p;
p=&a[0];
++*p;	//指針指向地址中的數值加1
printf(“%#p\n”,p);	//打印指針變量p所指向的地址編號
p++;	//指針移動到數組元素a[1]的位置
printf(“%#X\n”,p);	//打印移動后指針變量p所指向的地址編號
//指針變量++(或--)移動一次是移動其基類型大小的內存區域

for(int i=0;i<10;i++)
{
	printf(“%d”,*(p+i));	//通過指針移動引用數組元素,輸出數組
    //指針本身位置不改變
}
for(int i=0;i<10;i++)
{
	printf(“%d”,p[i]));	//通過指針帶下標的形式引用數組元素
    //[]相當於*解引用
}
for(int i=0;i<10;i++)
{
	printf(“%d”,*(a+i));	//通過數組首地址帶下標的形式引用數組元素
	//這里不能使用*a++,數組的首地址是一個地址常量,其指向不能被改變
}
for(int i=0;i<10;i++)
{
	printf(“%d”,*p++);	//指針本身的偏移(指針指向的改變)
    //如果使用指針本身偏移后,再使用*(p++)就指向數組外面未知區域去了
}

4、指針指向字符串

char *p = “abcdefg”;	//通過字符指針直接引用字符串
//字符串是一個字符數組,其首地址是地址常量
while (*p)
{
	printf("%c\t", *(p++));
}	


int* p;
char* str = "abcdefg1234567890";
p = (int*)str;	//將str強轉成int*類型
for(int i=0;i<strlen(str);i++)
{
	printf(“%d”,*(p+i));	
}
//輸出ae26 +亂碼,因為p指針一次移動4個字節,不是一個1字節


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM