博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言的灵魂—指针
阅读量:3900 次
发布时间:2019-05-23

本文共 5023 字,大约阅读时间需要 16 分钟。

C语言的灵魂—指针

指针是什么

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。总结来说,指针就是指向地址的变量!

指针的作用

c语言指针可以有效地表示复杂的数据结构、动态分配内存、高效地使用数组和字符串、使得调用函数时得到多个返回值等。指针的应用往往与数组联系在一起,是最频繁的,也是最基础的。参数传递时只需要拷贝地址值,提高程序的运行效率。有效的表示数据结构,能动态分配内存。

指针

指针的语法

指针变量的定义: 类型 * 指针变量名

&:表示取地址操作
*: 表示取地址中的值

怎么去理解指针

大家可能一时半会可能很难理解指针含义。我们的计算机都会有一个内存,并且这个内存的每一个部分有一个标记表示它的位置,这个标识就是我们的地址,地址对应的区域存放的就是我们的数据(值)。就像我们住酒店,酒店是内存,门牌号是我们的地址,住在房间里的人就是我们的数据!

代码示例

#include
int main(){ int num = 10; double num2 = 10.0; int * p ; p = # //这种不同类型的变量之前的操作是不合法的 // p = &num2; printf("p = %p\n",p); printf("num = %d\n",num); printf("*p = %d\n",*p); // num 和 p代表的是同一个地址的数据, // 当使用 *p 去修改数据的时候,num代表的数据也会改变! *p = 11; printf("p = %p\n",p); printf("num = %d\n",num); printf("*p = %d\n",*p); return 0;}/* 运行结果: p = 0x7ffee1eee7c8 num = 10 *p = 10 p = 0x7ffee1eee7c8 num = 11 *p = 11*/

通过以上代码我们不难理解:指针变量中,p 存放的是地址,*p 是取地址对应的值。num 变量直接存放地址对应的值!当我们使用 *p 修改数据的时候,我们 num 的存放的值也会发生改变!我们使用 & 符号即可取出变量的地址

举个例子,p 存放的是门牌号,*p 代表居住的客人,num 也是代表这个门牌号下居住的客人,当使用 *p 修改掉居住的人,num 也会发生相应的改变,因为他们代表的都是这个门牌号下居住的人。&num 即代表取出这个客人的房间门牌号

什么是双重(n重)指针

我们根据之前的解释可以知道,每个变量在内存中都有一个地址相对应。双重指针实际上存放的全是地址。

代码示例

#include
int main(){ int num = 10; int * p; p = # // 双重指针 int ** q; // 指针变量也是变量的一种,即 p 也是有对应的地址 // &p 即取 p 变量的地址 q = &p; // p 变量存放的地址 ,即num变量的地址 printf("p = %p\n",p); // p 变量自身的地址 printf("p = %p\n",&p); // q 存放的地址就是 p 变量自身的地址 printf("q = %p\n",q); // *p == num printf("*p = %d\n",*p); // **q == *p == num printf("**q = %d\n",*p); return 0;}/* 执行结果: p = 0x7ffee910c7c8 p = 0x7ffee910c7c0 q = 0x7ffee910c7c0 *p = 10 **q = 10*/

图解

n重指针

n重指针同理


数组实际上使用的就是指针,我们再学习下数组类型

指针函数和函数指针

指针函数

顾名思义,指针函数就是返回值为指针的函数

语法示例

#include 
int *fun(int a, int b, int *p){ *p = a + b; return p;}int main(){ int *p; p = fun(10, 10, p); printf("%d \n", *p); return 0;}/* 执行结果: 20*/

函数指针

函数指针就是指向函数的指针。一个函数标识符就表示了它的地址

示例代码

#include 
int add(int a, int b){ return a + b;}int sub(int a, int b){ return a - b;}int (*fun)(int a, int b);int main(){ // 函数指针用法一 fun = add; //调用方法二 printf("%d \n", fun(10, 10)); //用法二 fun = ⊂ //调用方法一 printf("%d \n", (*fun)(10, 10)); return 0;}/* 执行结果: 20 0*/

一维数组

语法规则

类型名 变量名 [数组大小]

字符串数组:C语言中一个字符串的界定范围是 ‘\0’,当遇到’\0’时认为字符串已经结束

语法示例

#include
int main(){ char chs[100] = {'a','b','c','\0'}; printf("chs = %s\n",chs); //指针版示例 printf("point verion:\n"); printf("chs = "); for(int i = 0; *(chs + i) != '\0';i ++){ printf("%c",*(chs + i)); } printf("\n"); return 0;}/* 运行结果: chs = abc point verion: chs = abc*/

我们从示例代码中可以看到: chs[i] 等价于 * (chs + i)

二位数组

语法定义

类型名 数组变量名称 [行数][列数]

代码示例

#include 
int main(){ //未初始化的数组其值是不确定的 int arr[7][7] = {0}; //输入行数 printf("%lu\n", sizeof(arr) / sizeof(arr[0])); //输出列数 printf("%lu\n", sizeof(arr[0]) / sizeof(int)); //打印数组信息 数组实际上就是二维指针 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { for (int j = 0; j < sizeof(arr[0]) / sizeof(int); j++) { printf("%d ", (*(arr + i) + j)); } printf("\n"); } // 打印数组的地址信息 可以看到,数组实际上是一块连续的地址空间 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { for (int j = 0; j < sizeof(arr[0]) / sizeof(int); j++) { printf("%p ", (*(arr + i) + j)); } printf("\n"); } return 0;}/* 执行结果: 7 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x7ffee5a9d700 0x7ffee5a9d704 0x7ffee5a9d708 0x7ffee5a9d70c 0x7ffee5a9d710 0x7ffee5a9d714 0x7ffee5a9d718 0x7ffee5a9d71c 0x7ffee5a9d720 0x7ffee5a9d724 0x7ffee5a9d728 0x7ffee5a9d72c 0x7ffee5a9d730 0x7ffee5a9d734 0x7ffee5a9d738 0x7ffee5a9d73c 0x7ffee5a9d740 0x7ffee5a9d744 0x7ffee5a9d748 0x7ffee5a9d74c 0x7ffee5a9d750 0x7ffee5a9d754 0x7ffee5a9d758 0x7ffee5a9d75c 0x7ffee5a9d760 0x7ffee5a9d764 0x7ffee5a9d768 0x7ffee5a9d76c 0x7ffee5a9d770 0x7ffee5a9d774 0x7ffee5a9d778 0x7ffee5a9d77c 0x7ffee5a9d780 0x7ffee5a9d784 0x7ffee5a9d788 0x7ffee5a9d78c 0x7ffee5a9d790 0x7ffee5a9d794 0x7ffee5a9d798 0x7ffee5a9d79c 0x7ffee5a9d7a0 0x7ffee5a9d7a4 0x7ffee5a9d7a8 0x7ffee5a9d7ac 0x7ffee5a9d7b0 0x7ffee5a9d7b4 0x7ffee5a9d7b8 0x7ffee5a9d7bc 0x7ffee5a9d7c0*/

数组相关的函数

#include 
int main(){ char old[100]; char new[200]; int n = 10; //字符数组操作函数 //将旧数组的数据拷贝到的新的数组之中。旧数组的数据遇到了\0就停止复制。新数组的长度必须大于等于旧数组数据长度 + 1 strcpy(new,old); // 将旧数组的前n位字符拷贝到新数组中。新数组的长度必须大于等于新数组原数据长度 + 旧数组数据长度 + 1 strncpy(new,old,n); //两个字符数组进行比较。首先从第一位开始逐位比较,按照字典序的大小进行比较。遇到第一个不等的字符或者遇到了\0停止比较。等于返回0,new < old返回 -1,new > old 返回 1 strcmp(new,old); //将两个字符串进行连接。新数组的长度必须大于等于 新数组的数据长度 + 旧数组的数据长度 + 1 strcat(new,old); return 0;}

以上就是本期的全部内容了,感谢你能看到这里。我们下期见!

转载地址:http://atden.baihongyu.com/

你可能感兴趣的文章
静态库和动态库的区别
查看>>
线程池之newFixedThreadPool定长线程池
查看>>
线程池中shutdown()和shutdownNow()方法的区别
查看>>
MyBatis的PageHelper不生效问题
查看>>
Linux文件上传下载,rz和sz
查看>>
Zmodem transfer canceled by remote side
查看>>
java泛型
查看>>
json字符串转Bean和List时候打印Date的WARN级别日志
查看>>
static静态代码块执行次数
查看>>
get方法传递到后台中文乱码解决方法
查看>>
break和continue的区别
查看>>
解决springmvc文件下载,内容损坏问题
查看>>
velocity模板前端页面Date时间格式化
查看>>
mybatis的if test判断
查看>>
页面加载事件
查看>>
js中时间格式转换和ajax中拼接时间格式转换
查看>>
java中txt文件在线显示中文乱码问题
查看>>
Ajax的beforeSend用处
查看>>
jquery ajax报Uncaught TypeError :Illegal invocation错误
查看>>
java中html文件在线浏览,标签注入问题解决
查看>>