首页 > 其他分享 >C语言---指针的运算和各种类型的指针

C语言---指针的运算和各种类型的指针

时间:2024-08-09 17:24:57浏览次数:14  
标签:arr p1 int C语言 --- printf 内存地址 指针

指针的运算

1.指针+1或者指针-1是什么意思?

把指针中记录的内存地址,往后或者往前移动一个步长

2.什么是步长?跟什么有关?

跟数据类型有关

Windows64位操作系统:

char:移动一个字节

short:移动两个字节

int:移动四个字节

long:移动四个字节

long long:移动八个字节

有意义的操作 :

指针跟整数进行加、减操作(每次移动N个步长)

指针跟指针进行操作(间隔步长)

无意义的操作:

指针跟整数进行乘除操作

指针和指针进行加、乘、除操作

原因:此时指针指向不明

指针运算案例

前提:保证内存空间是连续的

#include<stdio.h>
main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9};
    int* p1 = &arr[0];
    int* p2 = &arr[5];
    printf("数组的0索引对应的元素是:%d\n",*p1);
    printf("数组的1索引对应的元素是:%d\n",*(p1+1));
    printf("arr[5]和arr[0]之间的间隔步长为:%d\n",p2-p1);
    printf("%p\n",p1);
    printf("%p\n",p2);
    return 0;
}

指向不明的指针

1.野指针

(指针指向的空间未被分配): 获取到的数据是其他程序的数据 (外挂的基本原理)

#include<stdio.h>
main()
{
​
    int a = 10; 
    int* p1 = &a;
    int* p2 = p1+10;    //将p1的内存地址加10个步长后的地址赋给p2  但p2是一个未被分配的内存地址
    printf("%p\n",p1);
    printf("%d\n",*p1);
    printf("%p\n",p2);
    printf("%d\n",*p2);
    return 0;
}
​
2.悬空指针

(指针指向的空间已分配,但被释放了)

#include<stdio.h>
int* test();
main()
{
    int* p3 = test();  //函数结束后内存空间被释放,里面的变量也被释放
    printf("%p\n",p3);
    printf("%d\n",*p3);
    return 0;
}
int* test()
{
    int a = 10;
    int* p = &a;
    return p;
}

void类型的指针

优点:

可以接收任何类型指针记录的内存地址

缺点:

无法获取其中的数据,也无法对其进行加、减计算

代码案例
#include<stdio.h>
void swap(void* p1,void* p2,int len);
int main()
{
    int a = 10;
    int b = 13;
    swap(&a,&b,sizeof(int));
    printf("a:%d   b:%d",a,b);
    return 0;
}
//函数:用于交换两个变量记录的数据
//使用viod型指针,提高函数通用性,任何数据类型的数据都可以进行交换
void swap(void* p1,void* p2,int len)    //定义两个viod指针来接受传递的内存地址,定义len接收外部数据的占用字节长度
{
    int i;      
    int temp = 0;
    //把void类型指针转成占用字节长度为一的char型,用于后面的字节级转换
    char* pc1 = (char*)p1;          
    char* pc2 = (char*)p2;
    //循环每一个字节进行交换
    for(i = 0;i < len;i++)
    {
        temp = *pc1;
        *pc1 = *pc2;
        *pc2 = temp;
        pc1++,pc2++;    //交换完后,进行下一个字节的交换
    }
}

多级指针

含义:

指向指针的指针

作用:

多重指针可以操作它指向的指针中的内存地址

代码案例

逻辑如下

int ** pp = p

其中的int*是p的变量类型; *是标记这是个指针变量

当使用多重指针时

*pp = &b

*是解引用运算符,代表解一次,所以此时就是p,而p保存的是内存地址,所以就代表把p的内存地址改为p的内存地址

**pp

解两次,解1次是p,p保存的是内存地址,再解一次就解成了b,b保存的是具体的值,所以此时就是输出b的值

#include<stdio.h>
int main()
{
    int a =10;
    int b =20;
    //定义指针保存变量a的内存地址
    int* p = &a;
    //定义指针保存指针变量p的内存地址
    int** pp = &p;
    //把p中的内存地址修改为为b的内存地址  
    *pp = &b;
    printf("a的内存地址为:%p\n",&a);
    printf("b的内存地址为:%p\n",&b);
    printf("指针p的内存地址为:%p\n",p);
    printf("指针pp的值为:%d\n",**pp);
    return 0;
}

数组指针

获取数组的指针,实际上是获取数组的首地址

代码案例

#include<stdio.h>
int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9};
    int length = sizeof(arr) / sizeof(arr[0]);
    int* p = arr;       //获取数组首地址
    //int* p = arr[0];    这行代码和上面效果一样
    int i;
    for(i = 0;i < length;i++)
    {
        printf("%d ",*(p+i));//*(p+i):首地址也就是0索引的元素,获取完0索引元素后,地址往后移一位就是1索引,以此类推
        
    }
    printf("\n");
    return 0;
​
}
数组指针的细节

arr参与计算的时候,会退化为第一个元素的指针

特殊情况:

sizeof 运算的时候,不会退化,arr还是整体

&arr获取地址的时候,不会退化,步长:数据类型*数组长度

标签:arr,p1,int,C语言,---,printf,内存地址,指针
From: https://blog.csdn.net/2301_80464770/article/details/140995650

相关文章

  • 解决Pytest UnknownMarkWarning: Unknown pytest.mark.single - is this a typo?
    解决PytestUnknownMarkWarning:Unknownpytest.mark.single-isthisatypo?出现截图所示问题前提:1.项目中使用了mark标记:@pytest.mark.single2.同时项目中包含pytest.ini文件并进行了pytest.ini配置运行项目运行时报出截图所示Warning解决方法:切换运行项......
  • Datawhale AI夏令营-第四期(AIGC方向)-Task01-可图Kolors-LoRA风格故事挑战赛
    从零入门AI生图原理&实践是Datawhale2024年AI夏令营第四期的学习活动(“AIGC”方向),基于魔搭社区“可图Kolors-LoRA风格故事挑战赛”开展的实践学习。下面将分六部分介绍我的学习&实践情况。一、文生图的历程与基石首先,通过社区提供的学习资料和PPT,对文生图的历程与基石进......
  • AP5101C 6-100V 2A LED降压恒流型的线性调光驱动器 台灯手电筒与汽车灯方案
    产品描述AP5101C是一款高压线性LED恒流芯片,外围简单、内置功率管,适用于6-100V输入的高精度降压LED恒流驱动芯片。最大电流2.0A。AP5101C可实现内置MOS做2.0A,外置MOS可做3.0A的。AP5101C内置温度保护功能,温度保护点为130度,温度达到130度时,输出电流慢慢减小,达到保护芯片电路......
  • 字符函数和字符串函数(C语言)
    目录一.字符分类函数二.字符转换函数三.多种函数的使用和模拟实现3.1strlen函数3.2strcpy函数3.3strcat函数3.4strcmp函数3.5 strncpy   strncat   strncmp ......
  • 《DNK210使用指南 -CanMV版 V1.0》第十八章 machine.Timer类实验
    第十八章machine.Timer类实验1)实验平台:正点原子DNK210开发板2)章节摘自【正点原子】DNK210使用指南-CanMV版V1.03)购买链接:https://detail.tmall.com/item.htm?&id=7828013987504)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html5......
  • UBOOT以太网驱动程序指南, uboot网卡驱动指南,u-boot网卡驱动编译教程
    以太网驱动程序指南DasU-Boot中的网络堆栈设计允许在运行时轻松添加和控制多个网络设备。本指南适用于希望回顾网络驱动堆栈并实现自己以太网设备驱动程序的人员。在这里,我们将描述一个新的伪“APE”驱动程序。大多数现有驱动程序已经(并且新的网络驱动程序必须)使用U-Boot核......
  • SciTech-EECS-一次完成“电子”和“机械”统一设计: 3D化PCB(电路板)设计 与 solidwor
    AltiumDesigner做PCB设计。AltiumDesigner导出PCB设计为3D封装的设计文件。SolidWorks导入AltiumDesigner导出的3D设计文件。SolidWorks做整个产品的3D模型。https://wenku.baidu.com/view/138bd7b9700abb68a982fbca.html?wkts=1723191378929&needWelcomeRecomman......
  • 远程桌面授权服务远程代码执行漏洞(CVE-2024-38077)漏洞预警
    影响范围开启了RDL服务的WindowsServer2000到2025都会受到影响满足以上条件可以直接RCE关于RDL服务名全称,RemoteDesktopLicensing,如图:这个就是RDL服务,一般运维应该不会刻意去安装这个的,常用自带默认的远程桌面服务加个白名单就够了:解决办法1、没装RDL服务的不用管2......
  • 数据分析与应用:微信-情人节红包流向探索分析
    目录0需求描述1红包发送方用户的基本信息缺失率有多高?(即有多少红包发送方用户无法在用户基本信息表中匹配?2 哪一组红包金额的拒收率最高?3、最受二线城市欢迎的红包金额为?(即发出次数最多)4北上广深4大城市中,哪座城市的男性用户发出的520红包比例最低?5、将用户划分......
  • Java小白入门到实战应用教程-Scanner类及IO流讲解
    Java小白入门到实战应用教程-Scanner类及IO流讲解Scanner类我们前面写的很多例子都是程序独自执行的,但是我们做编程写代码的目的是要实现能人和代码去交互的。现在我们就来了解一个知识点,去实现最简单的人和程序的交互。在java中通过Scanner类来获取用户在控制台的输入......