初识指针

初识指针

一、什么是指针?

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

如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。

例如:整型变量分配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字节

posted @ 2021-11-24 21:10  宣哲  阅读(478)  评论(0编辑  收藏  举报