初阶指针(纯干货!!!)上

简介: 初阶指针(纯干货!!!)

前言


相信大家对指针应该不陌生吧,本文能带大家从零开始认识指针,了解指针的一些常用方法,并为后期指针学习打下良好基础。


指针是什么?


指针是什么?


  1. 指针是内存中一个最小单元的编号,也就是地址。
  2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。

总结:指针就是地址,口语中说的指针通常指的是指针变量


9ced49f54a7f48e78c9c09f0ecb3b905.png


每个长条都有自己的编号,它的编号就是地址,也就是指针。


指针变量


我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量。


#include <stdio.h>
int main()
{
  int a = 10;//在内存中开辟一块空间
  int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
//中,p就是一个指针变量。int* 表示p变量的类型是int型指针。
  return 0;
}


一个小的单元到底是多大?


对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);

那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

11111111 11111111 11111111 11111111

这里就有2的32次方个地址。

每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB ==

2^32/1024/1024MB ==2^32/1024/1024/1024GB == 4GB) 4G的空间进行编址。

同样的方法,那64位机器,如果给64根地址线,那能编2^32*4G的空间。


这里我们就明白:


在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。

那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。


总结:

指针变量是用来存放地址的,地址是唯一标示一个内存单元的。

指针的大小在32位平台是4个字节,在64位平台是8个字节


指针和指针类型


我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?

准确的说:有的。

当有这样的代码:


int num = 10;
p = &num;


要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢?

我们给指针变量相应的类型。


char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;


这里可以看到,指针的定义方式是: type + * 。

其实:

char* 类型的指针是为了存放 char 类型变量的地址。

short* 类型的指针是为了存放 short 类型变量的地址。

int* 类型的指针是为了存放 int 类型变量的地址。

那指针类型的意义是什么?


指针±整数


我们来分析下图:


baca0a5d3a4548cbad1fd8c840ddc850.png


指针类型决定了:指针进行解引用操作的时候,访问几个字节(权限)。

char* 的指针解引用访问一个字节

int* 的指针解引用访问4个字节

double* 的指针解引用访问8个字节


再来分析:


df6c72181dd14d02a324dd3355cce8db.png


指针类型决定了指针的步长(向前 / 向后 ,走一步都多大距离)

int * 指针+1,意思是跳过一个整型,也就是向后走4个字节。

char * 指针+1,意思是跳过一个字符,也就是向后走1个字节。

double * 指针+1,意思是跳过一个 double,也就是向后走8个字节。

short * 指针+1,意思是跳过一个short,也就是向后走2个字节。


野指针


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


野指针成因


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


  1. 指针越界访问
#include <stdio.h>
int main()
{
  int arr[10] = {0};
  int *p = arr;
  int i = 0;
  for(i=0; i<=11; i++)
  {
    //当指针指向的范围超出数组arr的范围时,p就是野指针
    *(p++) = i;
  }
  return 0;
}


  1. 指针指向的空间释放,后期会在动态内存开辟的时候详细讲解,这里提一下。


如何规避野指针


  1. 指针初始化
  2. 小心指针越界
  3. 指针指向空间释放,及时置NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性
#include <stdio.h>
int main()
{
  int *p = NULL;
  int a = 10;
  p = &a;
  if(p != NULL)
  {
    *p = 20;
  }
  return 0;
}

相关文章
|
7月前
|
存储 编译器 C语言
c语言进阶部分详解(指针初阶)
c语言进阶部分详解(指针初阶)
78 0
|
7月前
|
存储 编译器 C语言
C语言初阶⑦(指针初阶)知识点+笔试题(上)
C语言初阶⑦(指针初阶)知识点+笔试题
49 0
|
5月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
5月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
7月前
|
存储 C语言
『C语言初阶』第七章 -初识指针
『C语言初阶』第七章 -初识指针
|
6月前
指针初阶(2)
指针初阶(2)
32 0
|
6月前
|
存储 编译器 Perl
指针初阶(1)
指针初阶(1)
35 0
|
7月前
|
存储 编译器 C语言
C语言初阶⑦(指针初阶)知识点+笔试题(下)
C语言初阶⑦(指针初阶)知识点+笔试题
51 0
|
7月前
|
编译器 C语言 C++
初阶指针(C语言)
初阶指针(C语言)