C语言作为一门较为好上手的高级计算机语言,我相信任何一个开始学习编程的人都是先从他开始入手的,但是其中的指针曾叫人叫苦不迭。本文章旨在全面梳理C语言指针的知识点,内容非常宏大且精细,希望可以给看到本篇文章的人带来全新的指针认识。

本文为初阶版,我会尽快创作出高阶版的指针,喜欢本文的可以点个关注


本文章主要内容

  • 1. 什么是指针
  • 2. 指针的类型有哪些
  • 3. 野指针
  • 4. 指针的运算
  • 5. 指针和数组
  • 6. 二级指针
  • 7. 指针数组


1. 什么是指针

先来看看定义

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

int a=10;int *p=&a;p是指针变量,存放内存单元的地址(整形占四个字节,存放首地址,其他类型亦是如此)&a是a的地址,也就是指针存入p所以说&a或p唯一指向a

地址是如何产生的呢?
地址就是数据在内存中的存储位置的“门牌号”
计算机有32位和64位的配置,已32位为例:
就是有32根地址线,可以在寻址时产生32个电信号(正或负),将电子信号转换为数字信号就是32位的01序列(64位就是64位的01序列),地址编号就是由此产生的,但是为了便于观察,我们会用16进制来进行表示。
由此也可以推断出32位机器的指针大小为4字节(32bit==4byte),64位机器的指针为8字节。

2. 指针的类型有哪些

int *p1;char *p2;double *p3;float *p;…………这些指针虽然指向的数据类型不同,但本身大小都一样,那么为什么要给出这么多指针类型呢?难道不能只设置一种类型指向所有吗?比如pointer *p;接下来我们看看指针类型有什么用呢?

以上两个图片我们可以看到

int* 型的指针解引用访问了四个字节的内容
char* 型的指针解引用只访问了一个字节的内容
由此可以看出指针类型的第一个作用决定了指针的访问权限,即指针向后方访问几个字节
所以我们想要访问几个字节就用相对应字节数类型的指针进行存储。

从上图可看出不论是什么类型的指针存放的都是元素起始地址。
不同类型的指针+/-1所改变的距离不同这就是指针类型的第二个作用
所以我们如果用char*指针就可以把arr[10]当成四十个空间来使用。

3. 野指针


p得到地址时,地址指向的空间已经释放了,所以这个时候的p就是野指针。

野指针:指针指向的位置是不可知的。(随机的、不正确的、无明确限制的)

野指针形成原因共一下几种可能:

  1. 指针未初始化
#include<stdio.h>int main(){int *p;//此时p未初始化,里面是随机值,乱用会很危险*p = 20;return 0;}

  1. 指针越界访问
#include<stdio.h>int main(){int arr[10] = { 0 };int *p = arr;int i;for (i = 0; i < 11; i++){*(p + i) = i;}return 0;}

  1. 指针指向的空间释放

那么如何规避野指针呢?

  1. 指针初始化
int *p=NULL;//不知道要指向谁就置成空指针orint a=1;int *p=&a;//知道要指向谁

  1. 防范指针越界
  2. 指针指向空间释放后就及时置成空指针
  3. 指针使用前检验有效性
    指针置成空指针时是无法使用的
    要学会使用断言(assert)判断指针是不是空指针
#include<stdio.h>#include<assert.h>int main(){int *p=NULL;assert(p!=NULL);//上式为假会报错return 0;}

4. 指针的运算

  • 指针+/-整数

指针加减整数上面其实已经提到了,*(p+i)就是一种应用
再介绍一种

#include<stdio.h>int main(){int arr[10] = { 0 };int *p = arr;int i;for (i = 0; i < 10; i++){*p++ = i;}p = arr;//注意++对p产生了实际效果,所以要重置for (i = 0; i < 10; i++){printf("%d ", *p++);}return 0;}

  • 指针 - 指针

    由此可知,指针-指针得到的值的绝对值是两者之间元素的个数
    但是必须是两个指针指向同一块连续的空间,两个数组的话会造成不确定结果
  • 指针的关系运算
    其实际就是指针之间进行比较
#define N 5int main(){float arr[N];float *p;for (p = &arr[5]; p > &arr[0];){*--p = 0;}return 0;}

5. 指针和数组

数组是指针吗?
指针式数组吗?
答案统统都是No,数组是一堆相同类型元素的集合,指针只是一个变量
他们之间的关系是数组可通过指针来访问
数组名表示的是数组首元素的地址,所以就可以将其存入指针中
在说指针越界那里已有举例,在此就不再过多赘述了。
强调一点:(p+i)==&arr[i]

6. 二级指针

一个int型的变量的地址可以存放到一个指针变量里边,那么这个指针作为一个变量是否也可以存放在一个指针变量里边呢,这就涉及到二级指针的概念了。

int main(){int a = 1;int *p1 = &a;//一级指针int **p2 = &p1;//二级指针//p2->&p1,*p2->&a,**p2->a//以此类推,可以得到以下式子,但使用几率不大int ***p3 = &p2;int ****p4 = &p3;int *****p5 = &p4;return 0;}

7. 指针数组

指针数组是指针还是数组呢?
答案是数组。

int main(){//整形数组:存放整形元素的数组int arr1[10] = { 0 };//指针数组:存放元素为指针的数组int a, b, c, d, e;int *arr2[5] = { &a, &b, &c, &d, &e };//存放整形指针的数组char *ch[5] = { NULL };//存放字符指针的数组//介绍一下使用方法char *c[5] = {"hehe","haha","ohhhh"};int i=0;for(i=0;i<3;i++){printf("%s ",c[i]);}return 0;}
©著作权归作者所有:来自51CTO博客作者wx5f76ff0a08bef的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. C语言之漫谈指针(上)
  2. 最全C/C++教程 你需要的全都有!
  3. 数组,对象,传参解构; 访问器属性的get,set
  4. 最新整理:iOS面试题-面试常问问题(一)
  5. 0406作业
  6. leetcode(4)——寻找两个有序数组的中位数
  7. 最小生成树(C语言, prim算法)
  8. ES6的Set类型
  9. 数组元素排序之冒泡排序

随机推荐

  1. Android Studio 检测内存泄漏与解决方法
  2. ReactNative学习笔记——调用原生组件(And
  3. 基于Small及Weex的定制化APP方案
  4. Android之进程间通信(IPC)-Messenger
  5. 【Android Studio】解决adb not respondi
  6. Android初级第一讲---Android开发环境的
  7. 如何创建一个四位数的密码Android布局
  8. 微信小程序开发环境搭建
  9. 七牛---Android SDK断点续传与暂停上传De
  10. 编译Android4.3内核源代码