[C语言]-基础知识点梳理-指针

前言

各位师傅好,我是qmx_07,今天来讲解指针的知识点,之后的内容会持续更新!

内存和地址

想要学习指针,我们就要先谈谈内存和地址 是怎么一回事

 • 比如 我们在校园生活中,肚子饿了 有时候会不会 点个外卖,解决我们的饮食问题

 • 但是 外卖小哥取餐之后,来到 宿舍公寓,这里的房间都长得差不多,不能挨个进门喊吧,那是不是效率就很差

 • 只要 我们提供一个房间号,是不是就轻松很多,快速定位了呢 

 • 这个就是 地址的思想 (下面我们换算到计算器里)

(这边只是举个例子哦,正常情况下 外卖小哥 是送到校园门口,进不来的,只是引申概念)

在我们的计算机中,CPU想要处理数据,需要到内存里面读取,再存放回去,那我们是如何进行管理的呢?

 • 内存会划分成一个个内存单元,每个内存单元会存储1个字节--存放着8个比特位

 • 换算成现实生活中就是: 内存单元编号(门牌号),所以可以方便找到内存空间,在c语言中把这个单元编号又叫做指针

 • 内存单元编号 == 地址 == 指针

   理解了地址和内存的关系后,我们来看看 在c语言中创建变量的过程

如何理解编址

 • 为什么要编址? 因为内存中 地址很多,需要进行管理

 • 而 计算机中的编址是在硬件层面中完成的

 • 必须理解,计算机内是有很多的硬件单 元,⽽硬件单元是要互相协同⼯作的。所谓的协 同,⾄少相互之间要能够进⾏数据传递。

 • CPU和内存之间也是有⼤量的数据交互的,所 以,两者必须也⽤线连起来

我们需要关注一条线,地址总线

 • 32位机器有32根地址总线, 每根线只有两态,表⽰0,1【电脉冲有⽆】,那么 ⼀根线,就能 •表⽰2种含义,2根线就能表⽰4种含 义,依次类推。32根地址线,就能表⽰2^32种含 义,每⼀种含义都代表⼀个地址

 • 地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传⼊ CPU内寄存器

 • 而 32位操作系统 因此 能够管理 2^32=4,294,967,300 / 1024 / 1024 /1024 = 4G内存

64位操作系统,大家可以自行推导一下

 • 32位平台下地址是32个bit位,指针变量⼤⼩是4个字节

 • 64位平台下地址是64个bit位,指针变量⼤⼩是8个字节

指针和指针类型

指针变量和解引用操作符

我们通过取地址操作符(&)拿到的地址是⼀个数值,这个就是指针变量

再通过解引用操作符,获取数据(*)

画图表示的话:

因为pa 这个指针,里面存储着 a的地址,所以能根据地址,找到a,继而拿到值

指针变量类型的意义

我们先来看一下 这个例子:

为什么这里 都是将指针里面的内容改为0,结果不一样呢?

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)

char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节

指针 +- 整数

我们观察一下 不同指针变量+- 整数 会有怎样的变化?

char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节

结论:指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)

指针运算

指针+- 整数-for循环遍历数组

前面已经演示了 +-整数的效果,所以这边 是 怎么使用for循环,来遍历数组

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>


int main() 
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int* parr = &arr[0];
    int sz = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", *(parr + i));
    }
    return 0;
}

思路:获取数组的长度,再根据for循环,拿到第一个数组的地址,再依次增长4个单位长度,获取全部值

指针-指针

我们来用指针 模拟实现strlen函数,strlen: 获取字符串的长度

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>

int my_strlen(char* s)
{
    char* p = s;
    while (*p != '\0')
    {
        p++;
    }
    return p - s;
}

int main() 
{
    char arr[] = "hello world";
    int sz = my_strlen(arr);
    printf("字符串的长度是:%d", sz);
    return 0;
}

思路:保存原始指针地址的位置,再解引用地址 一直增加到\0终止位置,两者相减,得到字符串距离

野指针

概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

指针未初始化

#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值 
 *p = 20;
 return 0;
}

指针越界访问

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>


int main() 
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int* parr = &arr[0];
    int sz = sizeof(arr) / sizeof(arr[0]);
    for(int i = 0; i < 11;i++)
    {
        printf("%d ", *(parr+i));
    }

    return 0;
}

指针指向的空间已释放

#include <stdio.h>
int* test()
{
 int n = 100;
 return &n;
}
int main()
{
 int*p = test();
 printf("%d\n", *p);
 return 0;
}

函数体里的变量 只在使用时有效,之后会进行销毁的操作,使用权限转移到操作系统,再去访问会出现问题

指针的有效性

int*p=NULL:
*p=10;

对空指针进行访问,也会出现问题

如何规避野指针

  1. 指针初始化
  2. 小心指针越界
  3. 指针指向空间释放即使置NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性

const修饰指针

• const作用:用来保护变量 不被修改

• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本⾝的内容可变。

• const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变

总结

介绍了 怎么使用指针,指针运算、以及const符的作用。指针还有一部分内容 下节继续分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值