指针
指针:指针是内存地址的抽象表示,用于标识数据在内存中的位置。在编程中,指针通常指的是指针变量,而指针变量的值是地址。
声明指针
格式:
int *p1; //p1为指针变量,指针变量p1的类型为(int*)。
char *p2; //p2为指针变量,指针变量p2的类型为(char*)。
间接运算符:“ * ”的作用是找出指针变量的值所对应的值(例:示例程序1第5点)。
注意:不同类型的变量,要声明相对应类型的指针变量来储存该变量的地址。
接下来通过示例程序来学习指针该如何使用。
示例程序1
//示例程序1
int main(void)
{
int value = 10;
int *p_value; //声明指针变量并分配地址
printf("value = %d,p_value地址为%p\n",value,&p_value);
p_value = &value; //p_value指向value的地址
printf("value = %d, value地址为%p\n",value,&value);
printf("value = %d, p_value值为%p\n",*p_value,p_value);
printf("通过value打印value=%d\n通过*p_value打印value=%d\n",value,*p_value);
return 0;
}
示例程序1运行结果:
//运行结果
value = 10,p_value地址为000000000065FE40
value = 10, value地址为000000000065FE4C
value = 10, p_value值为000000000065FE4C
通过value打印value=10
通过*p_value打印value=10
通过程序示例1我们知道:
1.指针在声明时就会分配为它本身分配一个内存地址;
int *p_value; //声明指针变量并分配地址
2.p_value指针指向value变量(p_value存储了value的地址),p_value本身地址没有发生改变。
p_value = &value; //p_value存储value的地址
3.可以使用%p直接通过&value的形式打印value的地址;
printf("value = %d, value地址为%p\n",value,&value);
4.可以使用%p通过指针变量p_value打印value的地址;
printf("value = %d,p_value地址为%p\n",*p_value,p_value);
5.*p_value等同于value,所以打印的value都为10;
printf("通过value打印value=%d\n通过*p_value打印value=%d\n",value,*p_value);
内存图理解:value和p_value在声明时就分配了相应的地址,而当p_value指向value时,p_value的值就为value的地址。
示例程序2
//示例程序2
int main(void)
{
int value1 = 10;
int value2;
int *p_value1;
int *p_value2;
printf("value1地址 = %p \n",&value1);
printf("value2地址 = %p\n\n",&value2);
p_value1 = &value1;
p_value2 = p_value1;
printf("value1 = %d, 指针p_value1值 = %p \n",value1,p_value1);
printf("value1 = %d, 指针p_value2值 = %p \n",*p_value1,p_value2);
printf("value2 = %d, 指针p_value2值 = %p\n\n",*p_value2,p_value2);
*p_value1 = 20; //通过p_value1指向的地址修改值
printf("value1 = %d, 指针p_value1值 = %p \n",value1,p_value1);
printf("value1 = %d, 指针p_value1值 = %p \n",*p_value1,p_value1);
printf("value2 = %d, 指针p_value2值 = %p\n\n",*p_value2,p_value2);
*p_value2 = 30; //通过p_value2指向的地址修改值
printf("value1 = %d, 指针p_value1值 = %p \n",value1,p_value1);
printf("value1 = %d, 指针p_value1值 = %p \n",*p_value1,p_value1);
printf("value2 = %d, 指针p_value2值 = %p\n\n",*p_value2,p_value2);
return 0;
}
示例程序2运行结果 :
//运行结果
value1地址 = 000000000065FE3C
value2地址 = 000000000065FE38
value1 = 10, 指针p_value1值 = 000000000065FE3C
value1 = 10, 指针p_value2值 = 000000000065FE3C
value2 = 10, 指针p_value2值 = 000000000065FE3C
value1 = 20, 指针p_value1值 = 000000000065FE3C
value1 = 20, 指针p_value1值 = 000000000065FE3C
value2 = 20, 指针p_value2值 = 000000000065FE3C
value1 = 30, 指针p_value1值 = 000000000065FE3C
value1 = 30, 指针p_value1值 = 000000000065FE3C
value2 = 30, 指针p_value2值 = 000000000065FE3C
通过程序示2例我们知道:
1.变量在声明时就会分配为它本身分配一个内存地址。
int value1 = 10;
int value2;
2.指针变量p_value2指向指针变量p_value1,从而间接获取到value1的地址,也就是说p_value1和p_value2指向的变量虽然不同,但访问到了相同的地址(value的地址)。
p_value1 = &value1;
p_value2 = p_value1; //p_value2指向p_value1指向的地址
3.可以通过*p_value1=20或*p_value2=30的方式更改所指向变量的值,也就是说通过变量的地址来更改变量的值(因为p_value1和p_value1的值相同,都为value的地址)。
...
*p_value1 = 20; //通过p_value1指向的地址修改值
....
*p_value2 = 30; //通过p_value2指向的地址修改值
...
内存图理解:value1、value2、p_value1和p_value2在声明时就分配了相应的地址,而当p_value1指向value时,p_value1的值就为value的地址;当p_value2指向p_value1时,p_value2的值就通过p_value1间接访问到value的地址。
总结:指针变量p是指向相同类型变量n的, 指针变量p的值就是变量n的地址;通过*p可以获取到n的值(*p等同于n)。
示例程序3:
//示例程序3
#include <stdio.h>
void ChangeValue(int *num1, int *num2);
int main(void)
{
int value1 = 10;
int value2 = 20;
printf("value1 = %d, value2 = %d\n",value1,value2);
ChangeValue(&value1, &value2); //填入地址而不是数值
printf("value1 = %d, value2 = %d\n",value1,value2);
return 0;
}
/*交换数值 num1和num2为指针变量*/
void ChangeValue(int *num1, int *num2)
{
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
示例程序3运行结果 :
//运行结果
value1 = 10, value2 = 20
value1 = 20, value2 = 10
通过程序示3例我们知道:
在定义函数时,声明的形参为指针变量,那么在调用函数时实参就必须传入相同类型的变量所对应的地址。
#include <stdio.h>
void ChangeValue(int *num1, int *num2);
int main(void)
{
...
ChangeValue(&value1, &value2); //填入地址而不是数值
...
return 0;
}
注:以上内容仅个人理解,不具备唯一性和绝对正确性,仅供参考。