欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C指针2:指针变量

程序员文章站 2024-01-01 21:14:58
...

前面已经介绍过数据在内存中的地址称为指针。

C语言中允许用一个变量来存放指针,如果一个变量存储的是一份数据的指针,那么这个变量称为指针变量。即指针变量的值是有一份数据的地址,这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。

举个例子:

有一个指针变量P,它的值是地址为0X01A。我们还有一个char类型的变量c,他存储的是“k”。即char c ="k";但是我们输出char类型的c所占用的地址为0X01A。

C指针2:指针变量此时可以说P指向c。

定义指针变量:

(1)知道了普通变量的定义规则,那么指针变量的定义就是在变量名前加*号即可,格式为:

datatype *name;//*表示这是一个指针变量,datatype表示该指针变量所指向的数据的类型。
//例如:
int *p1;//此时的p1是一个指向int类型数据的指针变量,至于p1究竟指向哪一份数据,应该由赋予它的值决定。
//形式如下
datatype *name=value;
//例如:
int a=10;
int *p_a=&a;//在定义指针变量p_a的同时对它进行初始化,并将变量a的地址赋予它,此时p_a就指向了a;此处p_a需要的是一个地址(注意是p_a需要的是一个地址,而不是*p_a),所以a前边必须要加取地址符,否则是不对的。

(2)同普通变量一样,指针变量也可以被多次写入,只要你想修改指针变量的值,随时都能够改变指针变量的值。举例如下:

//定义普通变量
float a=65.9,b=5.3;
char c='a',d='2';
//定义指针变量
float *p1=&a;//p1的类型是float*不是float//p1需要的是地址;//此处看见*号这个特殊的符号,表明定义的这个变量是指针变量,定义指针变量p1时必须带*号。下边对p1进行赋值时,见下。
char *p2=&c;//p2的类型是char*//p2需要的是地址;
//修改指针变量的值
p1=&b;//对p1进行赋值时,因为已经知道了p1是一个指针变量,所以就没必要再多此一举的带上*号,后边可以像使用普通变量一样来使用指针变量。
p2=&d;//即定义指针变量时必须带*号,给指针变量赋值时不能带*号。

p1,p2指向关系如下图:假设变量a,b,c,d的地址分别为0X1000、0X1004、0X2000、0X2004

C指针2:指针变量

(3)通过指针变量取得数据,(PS:看清楚获得的是数据数据数据)格式如下:

//指针变量存储了数据的地址,通过指针变量能够获取地址上的数据,格式如下:
*pointer//此处的*号为指针运算符,用来取得某个地址上得数据。

下面举一个例子看一下输出结果就知道了:

#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
	int a = 15;
	int *p = &a;//p指向a后,p本身的值就会变成a的地址。
	cout << a <<","<<p <<","<<*p << endl;//p是地址,*p是15,在指针变量前边加*表示获取指针指向的数据,或者说表示的是指针指向的数据本身。(此处就是说明了使用指针变量时的*与定义指针变量时的*号意义完全不同)
	printf("%d, %d,%#X\n", a, *p, p);  //两种方式都可以输出a的值,*p与a等价。
	return 0;
}

C指针2:指针变量

由前一节的介绍我们知道,CPU 读写数据必须要知道数据在内存中的地址,普通变量和指针变量都是地址的助记符,由上边我们可以看出*p和a输出的结果是一样的,但是他们的运行过程不一样,a只需要一次运算就能够取得数据,而 *p 要经过两次运算,多了一层“间接”。

假设变量 a、p 的地址分别为 0X1000、0XF0A0,它们的指向关系如下图所示:

C指针2:指针变量

程序被编译和链接后,a、p 被替换成相应的地址。使用 *p 的话,要先通过地址 0XF0A0 取得变量 p 本身的值,这个值是变量 a 的地址,然后再通过这个值取得变量 a 的数据,前后共有两次运算;而使用 a 的话,可以通过地址 0X1000 直接取得它的数据,只需要一步运算。

也就是说,使用指针是间接获取数据,使用变量名是直接获取数据,前者比后者的代价要高。

(4)通过指针修改内存上的数据

#include <stdio.h>
#include <iostream>
using namespace std;

int main() {
	int a = 1, b = 17, c = 2;
	int *p = &a;  //定义指针变量,(1)此时*p代表的是a中的数据,即*p=a;
	*p = b;  //通过指针变量修改内存上的数据//(2)将另一份数据赋值给他
	c = *p;  //通过指针变量获取内存上的数据//(3)再将它赋值给另外一个变量
	cout << a <<" , "<< b <<" , "<< c <<" , " <<*p << endl;
	printf("%d, %d, %d, %d\n", a, b, c, *p);
	return 0;
}

结果如下:

C指针2:指针变量

使用指针交换值的例子:

#include <stdio.h>
#include <iostream>
using namespace std;

int main() {
	int a = 10, b = 99, temp;//临时变量temp
	int *pa = &a, *pb = &b;
	cout << a << " , " << b << endl;
	printf("a=%d, b=%d\n", a, b);
	/*****开始交换*****/
	temp = *pa; //*pa=a=10 //将a的值先保存起来//因为下一个语句中a的值会被b的值覆盖
	cout << a << " , " << b << ","<<temp<<endl;
	*pa = *pb;  //将b的值交给a//a的值会被b的值覆盖
	*pb = temp;  //再将保存起来的a的值交给b
				 /*****结束交换*****/
	printf("a=%d, b=%d\n", a, b);
	return 0;
}

结果如下:

C指针2:指针变量

总结:

假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a&*pa分别是什么意思呢?

*&a可以理解为*(&a)&a表示取变量 a 的地址(等价于 pa),*(&a)表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,*&a仍然等价于 a(是一个int型的数据)。

&*pa可以理解为&(*pa)*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa(是一个地址)。

ps:星号*主要有三种用途:

  • 表示乘法,例如int a = 1, b = 2, c;  c = a * b;,这是最容易理解的。
  • 表示定义一个指针变量,以和普通变量区分开,例如int a = 10;  int *p = &a;
  • 表示获取指针指向的数据,是一种间接操作,例如int a1, b1, *p = &a1;  *p = 100;  b1 = *p;
相关标签: C++

上一篇:

下一篇: