Working with pointer
经前一节我们已经学习了指针的基础. 本节我们将会用一些案例来看看在实际代码中怎样来使用指针.
在此之前让我们来快速回顾一下前一小节的内容.
-
Pointers
— variable that sotres address of another variable -
声明一个普通变量:
int a;
. 声明一个指针变量:int *p;
. 对于type *p
:type
类型的指针变量存储type
类型变量的地址. -
获得一个变量的地址:
p = &a;
— 指针p
存储变量a
的地址. -
通过指针操作指向的变量:
*p = 5;
— 地址位于p
的变量的值被修改为5
.
代码示例
下面我们将在实际的C
程序中使用指针. 对于不同的示例你可以先猜测输出的结果是什么. 为示例简便, 省略头文件以及main
函数的声明与返回.
example 1
int a;
int *p;
printf("%d\n", p);
example 2
int a;
int *p;
p = &a; //&a = address of a
printf("%p\n", p);
printf("%d\n", *p); //*p = value at address pointed by p
example 3
int a;
a = 10;
int *p;
p = &a; //&a = address of a
printf("%p\n", p);
printf("%d\n", *p); //*p = value at address pointed by p
printf("%p\n", &a);
example 4
int a;
int *p;
a = 10;
printf("a = %d\n", a);
p = &a;//&a = address of a
*p = 12;//dereferencing
printf("a = %d\n", a);
example 5
int a;
int *p;
a = 10;
p = &a;//&a = address of a
int b = 20;
printf("address of a = %p\n", p);
printf("address at p = %p\n", p);
printf("value at p = %d\n\n", *p);
*p = b;//p的地址会变成指向b的地址吗?
printf("address at p = %p\n", p);
printf("value at p = %d\n\n", *p);
p = &b;
printf("address pointed by p = %p\n", p);
printf("value at p = %d\n\n", *p);
样例输出
example 1
程序可能崩溃: 我们使用了没有初始化的指针p
. AcWing
编译器会将p
初始化为0
.
example 2
程序第一行输出一个地址; 第二行*p
会输出一个随机值(无用的值), 这是因为我们没有初始化变量a
.
example 3
程序第二行这一次输出a
初始化的值10
. 第一行和第二行输出一个相同的地址—变量a
的地址.
example 4
程序第一行输出10
— 变量a
初始化的值; 第二行输出12
, 我们通过对指向变量a
的指针变量p
进行
解引用操作修改了变量a
的值.
example 5
*p = b
不会将p
的值修改为指向b
的地址, 而是通过解引用操作将b
的值赋给了a
.
结束了我写你猜, 这里再介绍一个概念 — 指针运算.
指针运算 pointer arithmetic
int a = 10;
int *p;
p = &a;
//指针运算
printf("p = %p\n", p);
printf("p+1 = %p", p + 1);
printf("size of integer id %d bytes\n", sizeof (int));
-
首先的问题是: 我们可以这样做吗? 也就是我们可以增加或减少一个指针变量吗?
答案是可以! (只限于加减).
-
接下来的问题:
(p + 1)
的值是多少? 如果我们假设p = 2020
, 那么(p + 1)
的值是等于2021
吗?实际上
p + 1
的值是2024
. 这是因为这里p
是一个指向整型类型的指针, 对它进行+ 1
操作, 会得到下一个整型数据的地址. 因为$sizeof (int) = 4$, 所以为得到下一个整型数据的地址, 我们会跳过当前int
的4
字节,p + 1
会增加4
字节.
对于type *p
,p + x
的值等于$p + sizeof (type)\times x $
如果这时我们打印*(p + 1)
的值会发生什么?
int a = 10;
int *p;
p = &a;
//指针运算
printf("p = %p\n", p);
printf("value at address p is %d\n", *p);
printf("p+1 = %p\n", p + 1);
printf("value at address p+1 is %d\n", *(p+1) );
*p
的值是10
, 即变量a
的值; 而*(p + 1)
会输出一个没有用的随机值, 因为实际上我们并没有为这个特定的内存地址分配一个整数变量. 这是在C
中使用指针算数运算的时候一个危险的地方: 利用指针运算, 你可以到达任何地方. 有时候这种操作会引起我们预料之外的行为. 建议你使用其他的数据类型执行上面的代码, 答案应该是类似的.