首页 > 技术文章 > C语言 - 指针 1.1:指针 | 多级指针 | 指针作参

self-epoch 2019-06-13 17:52 原文

指针

1 -  字节是最⼩的存储单元为了正确访问内存单元系统会使每个内存单元都有一个编号,这个编号称作地址。指针就是内存地址,习惯上把内存地址叫做指针

2 - 存放内存地址的变量称为指针变量。指针变量所占的字节数跟指针变量的类型无关,它是跟系统位数有关 (32 位下占 4 字节,64 位下占 8 字节)

3 - 指针变量只有加减运算且在运算时指针类型决定着指针变量所移动的字节数

4 - 如果出现 * 的地方前面有类型修饰符,此时 * 仅仅是修饰作用,告诉编译器:老子是一个指针;如果出现 * 的地方前面没有类型修饰符,此时 * 代表取值操作符,会把指针指向区域中的内容取出来

int a = 10; // 这是一个变量
int *p;     // 这是一个指针
*p;         // 取值:访问指针变量 p 指向的存储空间
p = &a;     // 指针变量 p 指向了变量 a 的地址
*p = 20;    // 使用指针修改变量 a 的值

5 - 代码示例

① 交换两个变量的值(指针用作参数)

 1 #include <stdio.h>
 2 void change(int *a,int *b){
 3     
 4     int temp = 0;
 5     temp = *a;
 6     *a = *b;
 7     *b = temp;
 8 }
 9 
10 int main(int argc, const char * argv[]) {
11     
12     int a = 100;
13     int b = 200;
14     printf("交换前:\na = %d b = %d\n", a,b);
15     change(&a, &b);
16     printf("交换后:\na = %d b = %d\n", a,b);
17     
18     return 0;
19 }

② 使用指针可以实现让一个函数处理多个值。如下函数不仅返回了两数之和,还能够得到两数之差

 1 #include <stdio.h>
 2 
 3 int SumAndMinus(int n1,int n2,int *n3){
 4     
 5     *n3 = n1-n2;
 6     return n1+n2;
 7 }
 8 
 9 int main(int argc, const char *argv[]) {
10     
11     int a = 10;
12     int b = 11;
13     int sum;  //
14     int minus;//
15     
16     sum = SumAndMinus(a,b,&minus);// 把地址作为参数传出
17     printf("和 = %d,差 = %d\n",sum,minus);
18     
19     return 0;
20 }

6 - 指针变量只能存储地址,而不是具体值

int *p2;
p2 = 200;// 错误

7 - 野指针:指针变量未经初始化就不要拿来间接访问它的存储空间

int *p3; // 未初始化的指针
printf("%p\n",*p3);// crash
int *p1;// 你当然可以这样搞,不过很危险
int d = 10.0;
p1 = &d;  
// 改正 
int *p1 = &d;
int d = 10;
int *p4 = &d;// &*p 和 &d 等价;  *&d 和 d 等价

多级指针

1 - 其实就是指向指针的指针的指针的指针......

① 先看一段代码

int a = 10;
int *p = &a;    // 一级指针:就是个指针
int **p1 = &p;  // 二级指针:指向指针 p 的指针
int ***p2 = &p1;// 三级指针:指向指针 p 的指针 p1的指针

说明:*p 访问 a;  *p1 访问 p;  *p2 访问 p1

② * p1   相当于访问指针变量 p,而 ** p1 相当于访问 a

    ** p2 相当于访问指针变量 p,而 *** p2 相当于访问 a

  n 级指针需要 n 个 * 才能访问到最终的内存地址      

 ③ int **p 可以把它分为两部分看:int* 和 (*p), (*p) 中的“*”表示 p 是一个指针变量,int* 表示指针变量 p 只能存放 int*型 变量地址

     对于二级指针甚至多级指针都可以把它拆成两部分,不论它是几级指针它实质上就是一个指针变量,指针变量就是一个 *,其余的 * 表示的是这个指针变量只能存放什么类型变量的地址。比如 int ****a 表示指针变量 a 只能存放 int***型 变量地址

值传递 | 地址传递

1 - 代码示例

 1 #include <stdio.h>
 2 
 3 // 值传递
 4 void newValue(int a){
 5     
 6     a++;// 形参发生变化
 7 }
 8 
 9 // 地址传递
10 void test_str(char s[]){
11     
12     s[0] ='w';// 形参指向的是实参的地址
13 }
14 
15 int main(int argc, const char * argv[]) {
16     
17     int x = 555;
18     newValue(x);
19     printf("%d\n",x);// 555  实参不会发生变化
20     
21     char c[] = "me";
22     test_str(c);// 传入地址
23     printf("%s\n",c);// we   实参发生变化
24     
25     return 0;
26 }

指针类型

1 - 任何类型的指针都只和系统位数有关,那么为什么还要为指针加上类型呢。对下面一段代码进行内存分析就可以大致了解到因指针类型不正确而带来的严重后果

1 int i = 2;
2 char c = 1;
3 int *p = &c;// int型 指针指向 char型 变量地址
4 printf("%d\n",*p); // 513
5 printf("%d\n",c);  // 1 

指针 p 访问的本应该是 1 个字节空间的数据,但因指针类型是 int,所以程序自然地从指向地址 0x0a 开始读取 4 个字节的数据,访问的数据从 1 变成了 513

推荐阅读