【C语言】初阶指针详解

目录

一、什么是指针?

1.指针变量 

2.指针大小

二、指针类型

三、野指针

四、指针运算

1.指针+-整数

2.指针-指针 

3.指针的关系运算

五、指针和数组

六、二级指针

七、指针数组


一、什么是指针?

  • 指针是内存中一个最小单元的编号,也就是 地址
  • 平时口头说的指针,通常是指的是指针变量(用来存放内存地址的变量)

说到指针,那么我们还要了解一下内存,内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节

为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。

变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。 

1.指针变量 

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

#include<stdio.h>
int main() 
{int a = 10;int* p = &a;//&a拿到a的地址//注意a占用4个字节,这里只是将a的第一个字节的地址放到p变量中//p 是一个指针变量return 0;
}

指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)

2.指针大小

指针是用来存放地址的,地址是唯一标示一块地址空间的

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

这里简单地介绍一下地址线

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

00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

...

11111111 11111111 11111111 11111111

2 ^ 32 (2的32次方 bit 转GB 是  4GB,即4G大的空间可以进行编址)

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

二、指针类型

我们知道 定义一个变量有许多 类型 有 int 、float 等。当然 指针 也是有类型的

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

 类型 *

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

指针类型的意义 指针类型决定解引用操作的时候,访问几个字节

指针+-整数

指针的类型决定了指针向前或者向后走一步有多大(距离)

指针的解引用

指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)

 char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节

下方代码经过调试得到 执行前三行代码 

 在执行一行得到

这里就可以看到解引用不同权限的区别了

三、野指针

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

造成野指针的原因

1.指针未初始化

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

2.指针越界访问

#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;
}

*(p++)  先解引用在++,可以改为 *p  = i; p++;

在这里指针越界访问,不能访问不属于你的空间。

3.指针指向的空间释放

那木我们如何避免野指针呢?

  • 指针要初始化
  • 小心指针越界
  • 指针指向空间释放 使其置 为 NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性
//检查有效性
#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.指针+-整数

#include<stdio.h>
int main() 
{int i = 0;int arr[10] = {1,2,3,4,5,6,7,8,9,10};int* p = arr;for (i = 0; i < 10;i++){printf("%d ",*p+i);}return 0;
}

2.指针-指针 

指针-指针的绝对值 是 指针与指针之间的元素个数(前提 指向同一块区域,指针的类型相同)

这里用一个模拟strlen()来进行说明

#include<stdio.h>
int my_strlen(char * str) 
{char* a = str;while (*a != '\0')a++;return a - str;
}
int main()
{char* p = "abcdef";int ret = my_strlen(p);printf("%d\n",ret);return 0;
}

 【结果】

return a - str ; //返回之间的元素个数(即字符的个数) 

3.指针的关系运算

注意:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

五、指针和数组

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}

我们发现 数组名  和  数组首元素地址 是一样的

这里我们又会说到

数组名一般表示的是数组首元素的地址

特殊情况  sizeof(arr),&arr  表示的都是整个数组

那么 把数组名当成地址存放到一个指针中

#include <stdio.h>
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,0 };int*p = arr; //指针存放数组首元素的地址int sz = sizeof(arr) / sizeof(arr[0]);for (int i= 0; i < sz; i++){printf("&arr[%d] = %p  <====> p+%d = %p\n",i,&arr[i],i,p + i);}return 0;
}

执行结果

 发现一样,所以 p+i 其实计算的是数组 arr 下标为i的地址

int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//            0 1 2 3 4 5 6 7 8 9//使用指针打印数组的内容int * p = arr;int i = 0;//arr-->p//arr == p//arr+i  ==  p+i//*(arr+i) == *(p+i) == arr[i]//*(arr+i) == arr[i]//*(i+arr) == i[arr]//3+5//5+3for (i = 0; i < 10; i++){//printf("%d ", *(p + i));printf("%d ", *(arr + i));//printf("%d ", arr[i]);//printf("%d ", i[arr]);//p指向的是数组首元素//p+i 是数组中下标为i的元素的地址//p+i 起始时跳过了i*sizeof(int)个字节}return 0;
}

六、二级指针

前面我们已经了解到 指针变量 存放地址的变量,指针变量也是变量 ,那指针变量的地址放到哪?

二级指针 来 存放指针变量

 

*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa 

//**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
int b = 20;
*ppa = &b;//等价于 pa = &b;
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

七、指针数组

指针数组是 数组   ,是存放 指针的数

int*arr[5];

整型指针数组 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61497.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于APP备案、小程序备案的问题,如何备案?

近日&#xff0c;工信部发布了关于开展移动互联网应用程序备案工作的通知。为落实相关法律法规要求&#xff0c;促进互联网行业规范健康发展&#xff0c;进一步做好移动互联网信息服务管理&#xff0c;现组织开展移动互联网应用程序&#xff08;以下简称 APP&#xff09;备案工…

【Echart地图】jQuery+html5基于echarts.js中国地图点击弹出下级城市地图(附完整源码下载)

文章目录 写在前面涉及知识点实现效果1、实现中国地图板块1.1创建dom元素1.2实现地图渲染1.3点击地图进入城市及返回 2、源码分享2.1 百度网盘2.2 123云盘2.3 邮箱留言 总结 写在前面 这篇文章其实我主要是之前留下的一个心结&#xff0c;依稀记得之前做了一个大屏项目的时候&…

搞定libstdc++.so.6 version GLIBCXX_3.4.21 not found

一、问题&#xff1a; 今天在安装whisper的时候&#xff0c;突然间报了这样一个错误&#xff1a; OSError: Could not load shared object file: libllvmlite.so Errors were: [OSError("/lib64/libstdc.so.6: version GLIBCXX_3.4.21 not found (required by /opt/con…

前端技术Vue学习笔记--003

前端技术Vue学习笔记 文章目录 前端技术Vue学习笔记1、Vue生命周期和生命周期的四个阶段1.1、Vue生命周期1.2、生命周期的四个阶段1.3、Vue生命周期函数<font colorred>&#xff08;钩子函数&#xff09; 2、小黑记账本&#xff08;案例&#xff09;3、工程化开发和脚手架…

风丘科技将亮相 EVM ASIA 2023

风丘科技将首次亮相 EVM ASIA 2023 WINDHILL will debut EVM ASIA 2023 ——可持续移动的未来 —The Future of SUSTAINABLE Mobility EVM ASIA 2023是亚太地区电气化的国际性展会&#xff0c;专注于新能源汽车、充电技术及汽车零件制造等。展会致力于促进包括充电站、交通…

【MySQL】表中的一条数据在磁盘上是如何存放的?

文章目录 1 InnoDB行格式2 COMPACT行格式2.1 记录的额外信息2.2 记录的真实数据 3 Dynamic & Compressed4 VarChar(n)中n的最大取值&#xff1f; 1 InnoDB行格式 不同的存储引擎一般是为实现不同的特性来开发的&#xff0c;真实数据在不同存储引擎中的存放格式一般是不同的…

mysql统计近7天数据量,,按时间戳分组

可以使用以下 SQL 语句来统计近7天的数据量&#xff0c;并按时间戳分组。如果某一天没有数据&#xff0c;则将其填充为0。 SELECT DATE_FORMAT(FROM_UNIXTIME(timestamp), %Y-%m-%d) AS date,COUNT(*) AS count FROM table_name WHERE timestamp > UNIX_TIMESTAMP(DATE_SUB…

专注于创意设计,为您的小程序和网站建设带来更多的可能性

随着移动互联网的快速发展&#xff0c;越来越多的企业开始关注小程序和网站建设&#xff0c;以此来拓展业务和提升品牌形象。 在这个领域中&#xff0c;创意设计扮演着关键的角色。它不仅可以帮助企业打造独特的形象和品牌&#xff0c;还能够提高用户体验和购买决策的效率。 因…

flask-migrate使用

1.介绍 # 表,字段发生变化&#xff0c;都会有记录&#xff0c;自动同步到数据库中--》django支持这种操作 # 原生的sqlalchemy&#xff0c;不支持修改表的 # flask-migrate可以实现类似于django的 python manage.py makemigrations #记录 python manage.py migrate …

探索未知,即刻搭建AI原生应用!WAVE SUMMIT Workshop等你来参加

你是否希望掌握大模型开发的秘诀&#xff1f;你是否渴望得到实践操作的机会&#xff1f;如果你的心中充满热情和期待&#xff0c;那么&#xff0c;WAVE SUMMIT 2023特别设置的Workshop将会是你的知识启航站&#xff01; 本次Workshop专注于AI开发与大模型应用&#xff0c;邀请一…

python爬虫实战(2)--爬取某博热搜数据

1. 准备工作 使用python语言可以快速实现&#xff0c;调用BeautifulSoup包里面的方法 安装BeautifulSoup pip install BeautifulSoup完成以后引入项目 2. 开发 定义url url https://s.微博.com/top/summary?caterealtimehot定义请求头&#xff0c;微博请求数据需要cookie…

容器——2.Collection 子接口之 List

文章目录 2.1. Arraylist 和 Vector 的区别?2.2. Arraylist 与 LinkedList 区别?2.2.1. 补充内容:双向链表和双向循环链表2.2.2. 补充内容:RandomAccess 接口 2.3 ArrayList 的扩容机制 2.1. Arraylist 和 Vector 的区别? ArrayList 是 List 的主要实现类&#xff0c;底层使…