by HPC_ZY
也是偶然,在一个项目中需要多次交换二维数组中的值,逐个操作确实耗时,就想能不能利用指针操作快速交换。成功后写此文,记录分享。
一、基础知识
通过几个例子谈谈变量、指针、地址、取地址等等
符号 | 名称 | 作用对象 | 作用 |
---|---|---|---|
& | 取地址符 | 变量 | 返回变量所在的地址 |
* | 取值符 | 指针(地址) | 返回指针指向地址里存储的值 |
一个简单的例子
/* 取值符与取地址符*/
void main()
{
// 初始化
int *a = new int[1];
a[0] = 123;
// 取指针指向的值
printf("a[0] = %d\n", a[0]); // 最常用的取值方式
printf("*a = %d\n", *a); // 利用取值符
// 取指针地址
printf("a = %0x\n", a); // 最常用的取地址(a本来就是指针,存的地址)
printf("&a[0] = %0x\n", &a[0]); // 利用取地址符
// 取存储指针的地址
printf("&a = %0x\n", &a); // 利用取地址符
// 结束
printf("done");
getchar();
}
某一次运行结果如下(每一次运行结果都是不一样的,因为会分配到不同地址)
操作 | 值 | 描述 |
---|---|---|
a[0] | 123 | 获取指针a指向的第一个内存地址中存储的值 |
*a | 123 | 获取指针a指向内存地址中存储的值 |
a | 0xf0595f40 | 获取指针a指向的地址 |
&a[0] | 0xf0595f40 | 获取指针a指向的第一个值的地址 |
&a | 0x58fffb48 | 获取指针a在内存中的地址 |
打个比方(如下图),就好比办公室内有8个工位,小a被安排到5号工位(即a的地址),他接收到任务1(a指向的地址),任务1的内容是做一个ppt(a指向地址中存放的值)。
那么对应起来就是,
1)a[0] / *a ——任务具体内容——指针指向的地址中存放的值
2) a / &a[0]——任务号——指针指向的地址
3) &a —— 工位——指针存放的地址
二、实例
用一些例子进一步说明、理解
- 交换两个变量的值
/*交换两个变量的值(排序算法中常用到)*/
void main()
{
// 初始化
int a = 23;
int b = 7;
int tmp;
// 显示
printf("a = %d\n", a);
printf("&a = %0x\n", &a);
printf("b = %d\n", b);
printf("&b = %0x\n", &b);
// printf("tmp = %d\n", tmp); 因为没有初始化,所以不能写这一句
printf("&tmp = %0x\n\n", &tmp);
// 交换
tmp = a;
a = b;
b = tmp;
// 显示
printf("a = %d\n", a);
printf("&a = %0x\n", &a);
printf("b = %d\n", b);
printf("&b = %0x\n", &b);
printf("tmp = %d\n", tmp);
printf("&tmp = %0x\n\n", &tmp);
printf("done");
getchar();
}
我某一次运行的结果如下表所示(每一次运行结果都是不一样的,因为会分配到不同地址)
a | b | tmp | &a | &b | &tmp | |
---|---|---|---|---|---|---|
操作前 | 23 | 7 | / | 0xee3ffa54 | 0xee3ffa74 | 0xee3ffa94 |
操作后 | 7 | 23 | 23 | 0xee3ffa54 | 0xee3ffa74 | 0xee3ffa94 |
从上表可以看出,交换只修改变量的值,不会修改变量在内存中储存的位置(地址)。这里顺便提一下,我们可以看到a,b,tmp的地址依次相差32(注意表中地址以十六进制显示),因为在我的电脑里int类型为32位。
- 交换两个指针变量的值
void main2()
{
// 初始化
int *a = new int[1];
int *b = new int[1];
a[0] = 27;
b[0] = 9;
int *tmp;
// 显示
printf("*a = %d\n", *a);
printf("a[0] = %d\n", a[0]);
printf("a = %d\n", a);
printf("&a = %0x\n", &a);
printf("b[0] = %d\n", b[0]);
printf("b = %d\n", b);
printf("&b = %0x\n", &b);
printf("&tmp = %0x\n\n", &tmp);
// 交换
tmp = a;
a = b;
b = tmp;
// 显示
printf("a = %d\n", a);
printf("&a = %0x\n", &a);
printf("b = %d\n", b);
printf("&b = %0x\n", &b);
printf("tmp = %d\n", tmp);
printf("&tmp = %0x\n\n", &tmp);
printf("done");
getchar();
}
我某一次运行的结果如下表所示(每一次运行结果都是不一样的,因为会分配到不同地址)
a | b | tmp | *a | *b | *tmp | &a | &b | &tmp | |
---|---|---|---|---|---|---|---|---|---|
操作前 | 0x23A35850 | 0x23A35890 | / | 27 | 9 | / | 0x7E7F5758 | 0x7E7F5778 | 0x7E7F5798 |
操作后 | 0x23A35890 | 0x23A35850 | 0x23A35850 | 9 | 27 | 27 | 0x7E7F5758 | 0x7E7F5778 | 0x7E7F5798 |
从上表可以看出,这次我们只交换了a,b指向的地址,而没有修改对应地址中存储的数值。
地址0x23A35850中依旧存的27,地址0x23A35890中依旧存的9。
就好比,小a小b安排到5、6号工位(即a、b的地址),又分别拿到任务1、任务2(a、b指向的地址);后面老板又让他们把任务交换一下,小a做任务2,小b做任务1(交换指向的地址)。自始至终呢,任务号对应的任务内容(两个地址中存放的值)并没有变。
其他
- 上述内容应该是对的,也不排除有说错的地方。
- 暂时写到这里,如果以后有更多理解和实例会继续补充。
- 欢迎大家讲出自己的理解。