【C语言】初识指针

news2024/9/28 23:22:35

目录

一、指针是什么

 二、指针和指针类型

三、野指针

四、指针运算

五、指针和数组

六、二级指针

七、指针数组


一、指针是什么

       指针就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同(指针本质就是地址)

     我们可以这么理解:

 

 😐1.指针是个变量,存放内存单元的地址/内存编号
        
#include <stdio.h>
int main()
{
	int a = 10;//在内存中开辟一块空间
	int* p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
	//将a的地址存放在p变量中,p就是一个之指针变量。
	return 0;
}
                😀总结: 指针就是变量,用来存放地址的变量。
               

 二、指针和指针类型

这里我们在讨论一下: 指针的类型 是什么?
        
         我们都知道, 变量有不同的类型 ,整形,浮点型等。那指针有没有类型呢?
         其实是:有的。

 

当有这样的代码时

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 类型变量的地址.
😐那指针类型的意义是什么?
指针+-整数
#include <stdio.h>
//演示实例
int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	printf("%p\n", &n);
	printf("%p\n", pc);
	printf("%p\n", pc + 1);
	printf("%p\n", pi);
	printf("%p\n", pi + 1);
	return 0;
}
😐总结: 指针的类型 决定了指针向前或者向后走一步有多大 (距离)。
指针解引用
int main()
{
	int n = 0x11223344;
	char* pc = (char*)&n;
	int* pi = &n;
	*pc = 0;   //重点在调试的过程中观察内存的变化。
	*pi = 0;   //重点在调试的过程中观察内存的变化。
	return 0;
}
😀总结:指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如 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;
}
        😀3. 指针指向的空间释放
        
        这里放在动态内存开辟的时候讲解,这里可以简单提示一下。
           
         如何规避野指针
        1. 指针初始化
        2. 小心指针越界
        
        3. 指针指向空间释放即使置NULL
        
        4. 指针使用之前检查有效性
#include <stdio.h>
int main()
{
    int *p = NULL;
    //....
    int a = 10;
    p = &a;
    if(p != NULL)
   {
        *p = 20;
   }
    return 0;
}

四、指针运算

       • 指针+- 整数
       • 指针-指针
       • 指针的关系运算
        😀指针+- 整数
#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
     *vp++ = 0;
}

      😀 指针-指针

int my_strlen(char *s)
{
       char *p = s;
       while(*p != '\0' )
              p++;
       return p-s;
}
for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0;
}

        😀指针的关系运算

for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0;
}
代码简化 , 这将代码修改如下:
        
        
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}
😐实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为 标准并不保证它可行
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许 与指向第一个元素之前的那个内存位置的指针进行比较。

五、指针和数组

数组名是什么?我们看一个例子:
#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;
}

运行结果:

😀可见数组名和数组首元素的地址是一样的。
😀结论: 数组名表示的是数组首元素的地址
    那么这样写代码是可行的:
    
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址

  既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。

  例如:
#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(i=0; i<sz; i++)
   {
        printf("&arr[%d] = %p   <====> p+%d = %p\n", i, &arr[i], i, p+i);
   }
    return 0;
}

   

运行结果:

 

六、二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是 二级指针

 

 

😐对于二级指针的运算有:
😍*ppa 通过对 ppa 中的地址进行解引用,这样找到的是 pa *ppa 其实访问的就是 pa
int b = 20;
*ppa = &b;//等价于 pa = &b;
😍**ppa 先通过 *ppa 找到 pa , 然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;
int arr1[5];
char arr2[6];

七、指针数组

       😍 1.指针数组是指针还是数组?
                答案:是数组。是存放指针的数组。
        
       😀 2.数组我们已经知道整形数组,字符数组。

 

        😐那 指针数组 是怎样的?
        
        
int* arr3[5];
        🫡arr3是一个数组,有五个元素,每个元素是一个整形指针

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

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

相关文章

2023年2月的十篇深度学习论文推荐

本月的论文包括语言模型、扩散模型、音乐生成、多模态等主题。 1、MusicLM: Generating Music From TextPage https://arxiv.org/abs/2301.11325 By Andrea Agostinelli, Timeo I. Denk, et al. 扩散模型和自回归离散模型都在生成音乐/音频显示出令人印象深刻的性能。 与最…

第45期:一条 SQL 语句优化的基本思路

SQL 语句优化是一个既熟悉又陌生的话题。面对千奇百怪的 SQL 语句&#xff0c;虽然数据库本身对 SQL 语句的优化一直在持续改进、提升&#xff0c;但是我们不能完全依赖数据库&#xff0c;应该在给到数据库之前就替它做好各种准备工作&#xff0c;这样才能让数据库来有精力做它…

FreeMarker生成word文档,固定word模板

该方法也就是通过freemarker生成固定的word文档&#xff0c;动态的word模板布局不能用该方法。 也就是必须有一个固定的模板文档是.ftl类型 如果初始文件为 需要手动改为&#xff1a; 也就是所有需要替换的地方&#xff0c;都需要有${XX}替换。 主要步骤为&#xff1a; 将 w…

JVM学习8: 字符串

基本特性 代表不可变字符序列final不可被继承实现了Serializable、Comparable等接口jdk8及以前使用final char[]存储&#xff0c;jdk9开始改为使用byte[]存储通过字面量方式给一个字符串变量赋值&#xff0c;此时字符串对象在字符串常量池里面 字符串常量池 字符串常量池不会…

《论文阅读》PAL: Persona-Augmented Emotional Support Conversation Generation

《论文阅读》PAL: Persona-Augmented Emotional Support Conversation Generation 前言简介思路出发点相关知识coefficient of determination任务定义模型框架实验结果前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到失望?…

企企通:企业供应商风险管理,如何用采购管理软件赋能?

企业采购过程中&#xff0c;最怕/最担心的事情无非是&#xff1a;供应链异常。供应链异常&#xff0c;也就是我们常说的供应链风险&#xff0c;可以简单分为需求风险、供应商风险、物流风险和财务风险四大类。其中&#xff0c;最为突出的风险便是供应商风险。从寻找合适的供应商…

用VSCode搭建Vue.js开发环境及Vue.js第一个应用

目录 一、VSCode安装 二、VSCode简单配置 三、Vue.js的下载和引入 四、Vue.js第一个应用 一、VSCode安装 Visual Studio Code是一个轻量级但功能强大的源代码编辑器&#xff0c;可在您的桌面上运行&#xff0c;可用于Windows&#xff0c;macOS和Linux。它内置了对JavaScrip…

阿里一P7员工为证明自己年入百万,晒出工资,却被网友...

阿里的工资在行业内确实是比较高的一类&#xff0c;之前网络上流传着阿里P7年入百万的消息也不是空穴来风&#xff0c;日前&#xff0c;有位阿里P7员工&#xff0c;为了证明自己的确年入百万&#xff0c;晒出了他的工资&#xff0c;网友们看完都沸腾了。什么情况&#xff1f;一…

BSN全球伙伴大会于本周五召开在即,重磅嘉宾演讲主题前瞻

“第三届区块链服务网络&#xff08;BSN&#xff09;全球合作伙伴大会”召开在即&#xff0c;将于2023年2月17日&#xff08;本周五&#xff09;在杭州市拱墅区举办。 BSN已邀请到来自国内外的行业专家学者与生态合作伙伴&#xff0c;与各界来宾就“建设数字中国”指导思想中的…

iOS 客户端 IM 消息卡片插件化

背景 目前探探 IM 聊天消息列表由于长年累月的代码堆积&#xff0c;对业务迭代产生了很多的困扰。所以趁着工作中的一些空隙&#xff0c;对聊天页消息卡片做了插件化&#xff0c;使得不同的消息类型&#xff0c;可以根据具体需求方便的增删迭代。下面分享一下自己重构过程中一…

项目经理,千万不要在这时候跳槽

早上好&#xff0c;我是老原。节后开工也一段时间了&#xff0c;有不少小友私信老原想要面试题库&#xff0c;大多都是想要跳槽涨薪的......当然除了在做准备的&#xff0c;也有不少朋友都在诉苦&#xff1a;其实&#xff0c;不少人回头去看自己过去经验感觉就像个打杂的&#…

PCB中的HDI板生产中的变化

关键词&#xff1a;HDI概述 HDI发展演变 HDI生产难点如果把一整个电子产业比作浩瀚的宇宙&#xff0c;那些智能电子设备就像宇宙中闪耀的星光&#xff0c;当你以“上帝”的视角手持放大镜去观察时&#xff0c;这些闪烁的星光点点其实都是一个个由精密的“自然规律”所“设计”好…

金三银四丨黑蛋老师带你剖析-CTF岗

作者丨黑蛋二进制是个庞大的方向&#xff0c;对应着许许多多方向的岗位&#xff0c;除了之前说过的逆向岗位&#xff0c;漏洞岗位&#xff0c;病毒岗位&#xff0c;还有专门打CTF的岗位&#xff0c;CTF是网络安全领域的一种比赛。普遍来讲&#xff0c;大学生学习网络安全都会参…

percona软件介绍 、 innobackupex备份与恢复

1. 常用的mysql备份工具 物理备份缺点&#xff1a; 跨平台差。备份时间长、冗余备份、浪费存储空间。 解释如下&#xff1a;如Linux操作系统和Windows操作系统之间&#xff0c;由于文件系统不一样&#xff0c;如Linux操作系统的文件系统是ext4、xfs&#xff0c;Windows操作系统…

K8s+SpringBoot+gRpc

本文使用K8s当做服务注册与发现、配置管理&#xff0c;使用gRpc用做服务间的远程通讯一、先准备K8s我在本地有个K8s单机二、准备service-providerpom<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.…

浅谈性能测试监控系统,做好关键指标的监控

随着业务的增长&#xff0c;服务器部署由单一架构向分布式集群架构转变&#xff0c;性能测试过程中指标监控也由单一服务器向集群服务器转变。 对于性能测试团队来说&#xff0c;需要建立起适用于测试的多机监控系统&#xff0c;以便后期顺利且高效地进行监控分析调优&#xf…

Java程序员拿下高薪offer需要具备哪些能力?这份Java面试专题汇总助你拿下心仪offer!!

背景今天这篇文章的灵感来自一个粉丝的亲身经历&#xff0c;想必也是求职浪潮中很多朋友的经历&#xff0c;内卷大环境找不到满意工作的人太多了&#xff0c;之前也有很多人问过我怎么才能找到不错的工作&#xff0c;甚至是进大厂&#xff0c;所以今天就借这位粉丝的经历来聊聊…

对JAVA 中“指针“理解

对于Java中的指针&#xff0c;以下典型案例会让你对指针的理解更加深刻。 首先对于&#xff1a; 系统自动分配对应空间储存数字 1&#xff0c;这个空间被变量名称b所指向即: b ——> 1 变量名称 空间 明…

linux下yum安装consul实现动态配置管理

一、yum安装consul #安装yum-utils yum install -y yum-utils#配置consul的下载仓库 yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo#必须上面步骤&#xff0c;不然会找不到仓库 yum -y install consul#查看版本 consul -v 二、启动…

基于深度学习的三维重建(二):pytorch的简单操作及DataLoader、Dataset类简介

目录 1.numpy举几个demo 2.pytorch基础 2.1 tensor介绍 3.简单版DataSet & DataLoader 4.模型构建 5.深度学习模型demo&#xff1a;手写文字识别 5.1 构建网络 5.2 前向传播过程 5.3 训练部分 5.4 测试部分 5.5 模型导出 5.6 模型测试 6.pytorch可视化工具ten…