小言_互联网的博客

C语言指针全归纳-初级版

328人阅读  评论(0)

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

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

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;//不知道要指向谁就置成空指针
or
int 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 5
int 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;
}

转载:https://blog.csdn.net/weixin_53451597/article/details/115023846
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场