9.5 查找地址:& 运算符
指针(pointer)用于存放变量的 地址。
之前使用的 scanf_s()就是用地址作为参数。
概括来讲,如果主调函数不使用 return 返回的值,则必须通过地址才能修改主调函数中的值。
以下是一些带有 地址参数 的函数以及 & 的用法。
若变量名为 name ,则 &name 就是其地址
pc 地址通常以十六进制显示
%p 是 输出地址 的转换说明
#include <stdio.h>
int main(void) {
char name[10] = { 0 };
printf("Please enter your name within 9 characters:\n");
scanf_s("%s", name, 10);
printf("Okey, your name is %s.\nAnd the address of it is:%p.\n", name, &name);
return 0;
}
结果:
Please enter your name within 9 characters:
Alice
Okey, your name is Alice.
And the address of it is:007CF890.
注意,在 C 中,被调函数 并 不能改变 主调函数 中 变量的地址
这样可以防止原始变量被被调函数中的副作用意外修改
9·6 更改主调函数中的变量
首先对比一下两个程序及其结果:
其功能都是要实现数值的转换
- interchange 函数是要对调 main()中的 x y 的值
#include <stdio.h>
void interchange(int u, int v);
int main(void) {
int x, y;
x = 5;
y = 10;
printf("Before: x = %2d y = %2d\n", x, y);
interchange(x, y);
printf("Now: x = %2d y = %2d\n", x, y);
return 0;
}
void interchange(int u, int v) {
int temp;
temp = u;
u = v;
v = temp;
}
Before: x = 5 y = 10
Now: x = 5 y = 10
- 然而从上述的结果看 x y 的值并未对调,我们添加 printf()函数来检查一下
#include <stdio.h>
void interchange(int u, int v);
int main(void) {
int x, y;
x = 5;
y = 10;
printf("Before: x = %2d y = %2d\n", x, y);
interchange(x, y);
printf("Now: x = %2d y = %2d\n", x, y);
return 0;
}
void interchange(int u, int v) {
printf("Before: u = %2d v = %2d\n", u, v);
int temp;
temp = u;
u = v;
v = temp;
printf("Now: u = %2d v = %2d\n", u, v);
}
Before: x = 5 y = 10
Before: u = 5 v = 10
Now: u = 10 v = 5
Now: x = 5 y = 10
- 我们发现,在被调函数中,u v 的值确实调换了,但把值传回 main()时,interchange()中的值却并不是 main()中的值,一般我们会想到在 interchange()中添加
return(u);
,但这只能传回一个值,为了传回两个值,就必须用到指针。
9·7 指针简介
指针 (pointer)是一个 值为内存地址 的变量(或数据对象)
(以下我们会将指针作为函数参数使用)
先看如下程序:
ptr = &pooh;
/*
这里 ptr 是指针名
pooh 是一个变量
&pooh 是变量对应的地址
*/
/*
这条语句我们解释为:
指针 ptr 指向 pooh
*/
借鉴数据结构的思想,指针表示为:
9·7·1 间接运算符 *
间接运算符(indirection operator):
也称作 解引用运算符
通过 指针 / 地址 间接地找到其原变量的值
#include <stdio.h>
int main(void){
int pooh = 233; //给变量 pooh 赋值
int val;
int* ptr; //指针使用前要声明,下一节讲述
ptr = &pooh; //将 pooh 的地址赋给指针 ptr
val = * ptr; //使用间接运算符 * 找到指针所指向的变量 pooh 的值
printf("val = %d", val);
return 0;
//程序的语句可以等价为:val = pooh
}
结果:
val = 233;
9·7·2 声明指针
声明指针变量时必须 指定 指针所 指向的数据类型
int * ptr;
//星号(*)表明声明的变量是一个指针
//类型说明符(int)表明指针所指向对象的类型
//此声明的含义是:ptr 是指针,* ptr 是 int 类型
星号(*)+ 指针名 = 指向对象的值
星号(*)和指针名中间的空格(space)问题:
- 我们约定:在声明类型时使用空格,在解引用变量时不使用空格
注意:
- 指针的值是地址,一般由十六进制的无符号整数表示
- 但指针不是整数类型,而是一个新的类型——地址
- ANSI C 专门为指针提供 %p 转换说明
9·7·3 使用指针在函数中通信
我们仍使用之前的程序:
#include <stdio.h>
void interchange(int u, int v);
int main(void) {
int x, y;
x = 5;
y = 10;
printf("Before: x = %2d y = %2d\n", x, y);
interchange(&x, &y); //此处调用了变量 x,y 的地址,所以在函数中要将它们声明为指针
printf("Now: x = %2d y = %2d\n", x, y);
return 0;
}
void interchange(int* u, int* v) { //将得到的地址赋给相应的指针
int temp; //定义中间变量
temp = *u; //u 的值是 &x,我们要改变地址上变量的值,所以要对 *u 进行操作
*u = *v;
*v = temp;
}
结果:
Before: x = 5 y = 10
Now: x = 10 y = 5
以下列举两种函数调用形式:
//第一种
function1(x);
//这种方式调用了变量的值
//对应的函数定义:
function1(int x)
//要求函数定义中的形式参数必须是一个与 x 的类型相同的变量
**********************************
//第二种
function2(&x);
//这种方式调用了变量的地址
//对应的函数定义:
function2(int* x)
//要求形式参数必须是一个指向正确类型的指针
如果要 计算 或 处理 值 ,则使用第一种函数调用
如果要在被调函数中 改变 主调函数 的 变量 ,就使用第二种函数调用
普通变量 把 值 作为基本量,把 地址 作为通过 & 运算符获得的 派生量
指针 把 地址 作为基本量,把 值 作为通过 * 运算符获得的 派生量
参考书籍
《C Primer Plus》