C 语言指针进阶

1.0 指针的定义

指针是内存中一个最小单元的编号(内存单元的编号称之为地址【地址就是指针指针就是地址】)指针通常是用来存放内存地址的一个变量。本质上指针就是地址:口语上说的指针起始是指针变量,指针变量就是一个变量,是一个用于存放地址的变量,指针指向的就是地址,通过这个地址可以找到对应的内存单元。

指针变量创建:

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{// a 是一个整型变量,占用4个字节内存空间int a = 10;// pa 是一个指针变量,指针变量是用来存放地址的int* pa = &a;return 0;
}

总的来说,指针变量是用于存放地址的变量,(存放在指针中的值被当做是地址处理),在32位的平台下一个指针变量的大小是4个字节,在64位地址的机器上指针变量的大小是8个字节。

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{char   *pc = NULL;short  *ps = NULL;int    *pi = NULL;double *pd = NULL;printf("%zu\n", sizeof(pc));printf("%zu\n", sizeof(ps));printf("%zu\n", sizeof(pi));printf("%zu\n", sizeof(pd));return 0;
}


2.0 指针与指针类型

指针类型的含义

1. 指针的类型决定的指针被解引用的时候被访问几个字节【所谓的解引用是官方的叫法,实际上就去获取地址当中的值,或者说是将地址当中的值取出来】,例如:int * 的指针,解引用访问4个字节,char * 的指针解引用是访问一个字节,推广到其他的参数时也是一样的。

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{int a = 0x11223344;int* pa = &a;*pa = 0;char* pc = (char*)&a;*pc = 0;return 0;
}

2. 指针的步长:理解指针步长的意义

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{int a = 0x11223344;int* pa = &a;char* pc = (char *) & a;printf("pa = %p\n", pa);printf("pa = %p\n", pa + 1);printf("pa = %p\n", pc);printf("pa = %p\n", pc + 1);return 0;
}

指针类型决定了访问内存一次可以访问几个字节,如果是char * 的指针类型,那么访问内存只能一个字节一个字节的进行访问,如果是int * 类型的指针类型,那么访问内存就是以一次4个字节进行访问, int * pc如果是pc + 1 的话那么就是跳过前面的4个字节。


注:不同类型指针占用类型大小相同的指针是不能混用的,因为两者存储在内存中的空间是不同的,int 类型存储的是int类型,float类型存储的是float类型。

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{int a = 0;int* pi = &a;  // pi 解引用访问4个字节,pi + 1 也是跳过4个字节float* pf =(float *)& a;// pf 解引用访问4个字节,pf + 1 也是跳过4个字节return 0;
}

3.0 野指针,指针,与指针运算

野指针的概念:指的是指针指向的位置是不可知的

int main
{// p没有初始化,就意味着没有明确的指向// 一个局部变量不初始化,放的是随机值int *p;// 这样做的方式就是非法的访问内存,这个时候p就是野指针*p = 10;
}

#define  _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <string.h>
#include "add.h"
#include <stdint.h>/*
****************************
*  DEF    :  指针    
*  参数   :  无参数
*  返回值 :  无返回值
*  时间   :  2024/7/14
*  作者   :  _沧浪之水_
****************************
*/int main()
{int arr[10] = { 0 };// 数组名表示数组首元素地址arr[0]int* p = arr;// 指针的越界访问也会造成野指针for (int i = 0; i <= 10; i++) {*p = i;p++;}return 0;
}

野指针:涉及到局部变量和全局变量知识

函数执行进入主函数:main

这个时候test() 函数被调用

通过return 返回a的地址地址返回后int a 由于数局部变量出函数之后被销毁

这个时候 int *p 通过地址可以找到a这个空间
但是这个时候a空间已经被销毁,p这个时候无法访问和使用这个空间,这个时候这个p属于是野指针。

int * test()
{int a = 10;return &a;
}int main()
{int *p = test();return 0;
}


4.0 如何避免野指针

NULL 的值相当于是0 ,0 空间是没有办法被指针访问的,避免野指针的方式可以在初始化不知道赋值为什么的时候赋值为一个NULL也就是空指针,同时在使用之前先判断指针是否为空,如果指针为空就不使用,如果指针不为空的时候就对指针变量进行相应的操作,具体的示例如下所示。

避免野指针:

1: 指针初始化,

2:小心数组下标越界,

3:指针指向空间释放及时设置为NULL,

4:避免返回局部变量的地址,

5:使用指针之前先检查指针的有效性。

int * p = NULL;
int mian(void)
{if(p != NULL){*p3 = 100;}return 0;}

指针加减整数运算

#define N_VALUE 5
float values[N_VALUES];
float *vpfor(vp = &values[0]; vp < &values[N_VALUES];)
{*vp++ = 0;
}

int main(void)
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr)/sizeof(arr[0]);for(i = 0; i < sz; i++){// 把数组里面的值全部赋值为 1arr[i] = 1;}// int 类型的指针变量p,数组名等于数组首元素的地址int *p = arr;for(i = 0; i < sz; i++){// *P 解引用:也就是取值的意思*p = 1;p++;}// 使用指针步长的方式访问数组,进行数组操作for(i = 0; i < sz; i++){*(p + 1) = 1;}return 0;}

5.0 指针加减指针

int main(void)
{// 指针减去指针得到的绝对值得到的是指针之间元素的个数// 不是所有的指针都能相减,指向同一块空间的指针才能相减int arr[10] = { 0 };printf("%d\n",&arr[9] - &arr[0]); // 9
}

字符串长度:使用指针减去指针的方式

int my_strlen(char *str)
{*// str 刚开始起始地址是aint count = 0;while(*str != '\0'){count++;str++;}return count;
}
// 指针 - 指针
int my_strlen(char *str)
{char *start = str;while(*str != '\0'){str++;}return (str - start);}int main(void)
{int len = my_strlen("abcdef");printf("%d\n",len);}

指针的关系运算

#define N_VALUES 5
float values[N_VALUES]
float *vp;for(vp = &values[N_VALUES]; vp > &values[0];)
{*--p = 0;
}

C 语言标准规定指向指针的元素与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。


指针遍历访问数组

数组的定义:数组是一组相同元素的集合,指针变量是一个变量,存放的是地址,数组的数组名是首元素的地址 。

int main(void)
{int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *p = arr;int len = sizeof(arr)/sizeof(arr[0]);int i = 0for(i = 0; i < len; i++){printf("%d ",*(p + i));}for(i = 0; i < len; i++){// 打印输出的地址结果是相同的printf("%p-----------------%p\n",&arr[i],p + i);}return 0;
}

......

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

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

相关文章

MySQL覆盖索引和索引跳跃扫描

最近在深入学习MySQL&#xff0c;在学习最左匹配原则的时候&#xff0c;遇到了一个有意思的事情。请听我细细道来。 我的MySQL版本为8.0.32 可以通过 show variables like version; 查看使用的版本。 准备工作&#xff1a; 先建表&#xff0c;SQL语句如下&#xff1a; c…

SSM框架学习笔记(仅供参考)

&#xff08;当前笔记简陋&#xff0c;仅供参考&#xff09; 第一节课&#xff1a; &#xff08;1&#xff09;讲述了Spring框架&#xff0c;常用jar包&#xff0c;以及框架中各个文件的作用 &#xff08;2&#xff09;演示了一个入门程序 &#xff08;3&#xff09;解释了…

Redis 实现的延时队列组件

最近看开源看到一个好用的延时队列组件&#xff0c;已经上生产。代码量很少&#xff0c;主要就是利用Redis监听过期键实现的。然后搞点策略模式柔和柔和。利用Spring Start 封装了一下&#xff0c;全是俺掌握的知识&#xff0c;稍微研究了下就搞懂了。觉得挺有用的&#xff0c;…

006-三台交换机堆叠

三台交换机堆叠 链形连接和环形连接 链形配置IRF与环形配置IRF的区别 三个交换机链形配置IRF与三个交换机环形配置IRF的主要区别体现在以下几个方面&#xff1a; 物理位置要求&#xff1a; 链形连接&#xff1a;对成员设备的物理位置要求相对较低&#xff0c;主要适用于成员…

HybridCLR + Addressable 热更新篇(一)

目录 前言一、HybridCLR 和 Addressable 是什么&#xff1f;1. HybridCLR2. Addressable 二、使用步骤1.HybridCLR导入2.HybridCLR配置3.Addressable导入4.Addressable配置 前言 随着移动互联网和游戏行业的快速发展&#xff0c;热更新技术变得越来越重要。热更新能够在不重新…

图——定义和基本术语

图是数据结构中非常重要的一章&#xff0c;这篇文章就先介绍一下图的定义和基本术语。 一&#xff0c;图的构成 图&#xff1a;Graph(V,E) V&#xff1a;顶点(数据元素)的有穷非空集合&#xff1b; E&#xff1a;边的有穷集合。 如下面这个图&#xff0c;由点集和边集可以确定…

mupdf 编译说明

进入官网下载源码&#xff1a;https://www.mupdf.com/releases 挑选需要的版本&#xff0c;下载解压&#xff0c;然后打开解决方案&#xff0c;进行编译

python 怎样生成窗体

通过import tkinter导入Tkinter模块&#xff0c;没有这句下面的都不成立了。 wintkinter.Tk()&#xff0c;这句是创建windows的窗口对象&#xff0c;注意后面的Tk&#xff0c;大小写。 win.title("窗口")&#xff0c;这段是设置窗口上的标题。 另外窗口的大小你可以通…

java实战项目-学生管理系统(附带全套源代码)--《基础篇》

一、前言 第一个java小型学生管理系统&#xff0c;思路和其他语言都一样&#xff0c;因为有C语言的基础&#xff0c;写这个并不是太难&#xff0c;不过&#xff0c;进阶篇的就难太多了。明天晚上更新进阶篇&#xff0c;因为目前代码还没有完善&#xff0c;保守估计需要500行代…

网络请求优化:如何让你的API飞起来

网络请求优化&#xff1a;如何让你的API飞起来 亲爱的开发者朋友们&#xff0c;你是否曾经遇到过这样的场景:用户疯狂点击刷新按钮,你的服务器却像老年人散步一样慢吞吞地响应。或者,你的应用像个贪吃蛇,疯狂吞噬用户的流量包。如果你对这些情况再熟悉不过,那么恭喜你,你正需要…

Unity ColorSpace 之 【颜色空间】相关说明,以及【Linear】颜色校正 【Gamma】的简单整理

Unity ColorSpace 之 【颜色空间】相关说明&#xff0c;以及【Linear】颜色校正 【Gamma】的简单整理 目录 Unity ColorSpace 之 【颜色空间】相关说明&#xff0c;以及【Linear】颜色校正 【Gamma】的简单整理 一、简单介绍 二、在Unity中设置颜色空间 三、Unity中的Gamma…

部队物资仓库出入库管理系统|实现物资有效的战备保障

随着科技的不断发展&#xff0c;智慧营区已成为现代军事管理的重要方向。后勤物资管控作为营区管理的重要组成部分&#xff0c;对于保障营区正常运转和提高部队战斗力具有重要意义。智慧营区后勤物资管控平台作为数字化后勤建设的重要组成部分&#xff0c;能够实现营区物资的智…

Ubuntu下载安装chrome浏览器

方法一&#xff1a;wget下载并安装 1、创建文件夹存安装包 cd /root/Downloads mkdir chrome 2、下载安装包到文件夹内 wget -c https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -P /root/Downloads/chrome 3、安装 cd chrome sudo dpkg -i go…

药品类别功能助力智慧校园医务管理向前迈进

在智慧校园的医务管理框架下&#xff0c;药品类别管理模块发挥着举足轻重的作用&#xff0c;它以智能化的方式优化药品的存储、分配流程&#xff0c;确保每一步都符合安全与效率的标准。这一功能围绕着科学分类的核心理念&#xff0c;细致入微地组织药品信息&#xff0c;为校园…

TCP传输控制协议二

TCP 是 TCP/IP 模型中的传输层一个最核心的协议&#xff0c;不仅如此&#xff0c;在整个 4 层模型中&#xff0c;它都是核心的协议&#xff0c;要不然模型怎么会叫做 TCP/IP 模型呢。 它向下使用网络层的 IP 协议&#xff0c;向上为 FTP、SMTP、POP3、SSH、Telnet、HTTP 等应用…

威纶通触摸屏连接MySQL数据库步骤

目录 概要威纶通支持数据库的触摸屏类型测试Step 1 选择触摸屏型号Step 2 新增数据库服务器Step 3 添加SQL数据库查询功能Step 4 仿真测试 概要 通过使用威纶通带数据库类型的触摸屏&#xff0c;实现连接本地/远程MySQL数据库&#xff0c;并实现数据查询功能 威纶通支持数据库…

专业条码二维码扫描设备和手机二维码扫描软件的区别?

条码二维码技术已广泛应用于我们的日常生活中&#xff0c;从超市结账到公交出行&#xff0c;再到各类活动的入场验证&#xff0c;条码二维码的便捷性不言而喻&#xff0c;而在条码二维码的扫描识别读取过程中&#xff0c;专业扫描读取设备和手机二维码扫描软件成为了两大主要工…

ssh升级

文章目录 ssh升级一、解包ssh、ssl二、更新安装ssl三、手动更新手动复制库文件四、创建符号链接五、更新库路径六、验证库文件七、设置库路径环境变量八、配置、编译、安装OpenSSH&#xff1a;意外&#xff1a;缺少 zlib 的开发库解决方法&#xff1a; 九、刷新ssh服务、查看ss…

力扣第九题

回文数 提示&#xff1a; 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 代码展示&#…

AI绘画Stable Diffusion 零基础入门 —AI 绘画原理与工具介绍,万字解析AI绘画的使用教程

大家好&#xff0c;我是设计师阿威 想要入门 AI 绘画&#xff0c;首先需要了解它的原理是什么样的。 其实很早就已经有人基于深度学习模型展开了对图像生成的研究了&#xff0c;但在那时&#xff0c;生成的图像分辨率和内容都非常抽象。 直到近两年&#xff0c;AI 产出的图像…