C语言指针详解-上

C语言指针详解-上

  • 前言
  • 1.指针的基本概念
    • 1.1指针是什么
    • 1.2指针的声明与初始化
    • 1.3取地址符`&`和解引用符`*`
      • `&` 运算符用于**获取变量的地址**
      • `*` 运算符用于访问指针指向的值
  • 2.指针的类型
    • 常见数据类型的指针
    • 指针与数组、字符串
    • 数组指针
    • 结构体指针
    • 函数指针
    • 二级指针
    • void指针
  • 3.指针运算
    • 3.1指针的解引用
    • 3.2指针 + 整数、指针 - 整数
    • 3.3指针和指针的比较
    • 3.3指针-指针

前言

指针是C语言中一个绕不开的点,也是解题必备的工具,本文将围绕指针这几点进行详解:

  • 指针的基本概念
  • 指针类型
  • 指针运算
  • 指针的用途
  • 指针的安全隐患和解决方法
  • 常用工具

1.指针的基本概念

1.1指针是什么

在C语言中,任何变量的创建都需要在内存中申请空间,而这些空间都有特定的编号,即地址,也称作指针

地址也是一串数字,用于存放地址的变量就是指针变量,我们平常说的指针就是这个指针变量

1.2指针的声明与初始化

  • 在C语言中,声明指针主要分两步:
  • 使用解引用符(*)表明声明的变量是个指针
  • 指定一个指针指向的数据类型

如:

int* p1,p2;

*表明p1是个变量,int表明p1可以存储指向整型变量的地址
对于p2*和它没有关系,所以p2是个整型变量

  • 而在声明指针时,给指针一个具体的地址NULL就是初始化

如:

int x = 10; 
int *p = &x; 

这里创建了变量x,并使用取地址符(&)将x的地址存入p

1.3取地址符&和解引用符*

& 运算符用于获取变量的地址

在之前的学习中,我们应该多次使用了&:

int x;
scanf("%d", &x);

是的,当使用scanf函数读取变量,我们其实传递了变量的地址,这样scanf函数才能正确地将读取到的数据存储到那个变量中。

* 运算符用于访问指针指向的值

如:

int x = 10; 
int *p = &x; 
printf("%d",*p);

p是一个指向x的指针,那么*p就是x的值
我们也可理解为*获取了p中存放的地址,并通过这个地址找到了变量x

2.指针的类型

指针的类型大多取决它所指向的数据类型:

常见数据类型的指针

int *p1;
double *p2;
char *p3;

p1指向整型
p2指向双精度浮点型
p3指向字符

指针与数组、字符串

数组名大多情况下是指向数组首元素的指针:

int arr[10]={1,2,3,4,5,6,7,8,9,10};
for(int i=0;i<10;i++)printf("%d ",*(arr+i));
int* pa=arr;
for(int i=0;i<10;i++)printf("%d ",*(pa+i));

在这里插入图片描述
字符串实际上是一个字符数组,后面跟着一个空字符’\0’作为结束标志
因此,字符串的名字也是第一个字符的地址:

char ch[] = "Hello World!\n";
printf(ch);
char *pc = ch;
printf(pc);

在这里插入图片描述

数组指针

数组指针是指向一个具有固定数量元素的数组的指针。
因为只有元素数量固定,数组类型才能被确定:

int arr[10];     arr是个数组,元素个数10,元素类型为整型
int (*p1)[10];    p1是个指针,指向数组元素个数10,元素类型为整型
int (*p2)[10] = &arr;这是数组指针的初始化
p1 = &arr;这是数组指针的赋值

注:&数组名取出的是整个数组的地址

arr/&arr[0]&arr
数组首元素的地址整个数组的地址
类型int*int(*)[10]

结构体指针

声明和初始化的过程大同小异:

struct Stu
{int a;char c[20];
};
struct Stu S1;
struct Stu* p1;  声明
struct Stu* p2 = &S1;   初始化

需注意,当通过指针访问结构体成员时,可使用箭头运算符 ->,也可使用解引用符*

struct Stu S2={1,"Hello world!"};
p1 = &S2;
printf("%d\n",(*(p1)).a);
printf("%s\n",p1->c);

在这里插入图片描述

函数指针

函数名&函数名都是其地址,存放函数地址的变量就是函数指针:

int Add(int a,int b){return a + b;}
int (*p1)(int,int);   声明
int (*p2)(int,int) = &Add;初始化
int (*p3)(int,int) = Add; p2与p3相同

可以看见,函数指针声明也分两步:

  • 使用解引用符(*)表明声明的变量是个指针
  • 指定一个指针指向的函数类型

函数类型就是:返回类型(参数类型1,参数类型2…)
int(int,int)
其函数指针类型就是int(*)(int,int)

二级指针

指针变量也是一种变量,创建时会在内存开辟空间,而存储指针变量的地址的变量就是二级指针

int *p1;
int* *p2 = &p1;

其中,*p2*表明p2是个指针,int*表明p2指向指针变量,= &p1p1的地址存入p2

void指针

即以void声明的指针,无具体类型,可根据需要强制类型转换成所需的类型。
需注意,不强转就不能解引用

	int a = 0;void* p = &a;*p = 10;

在这里插入图片描述
在这里插入图片描述
但是可以直接使用其存储的地址,但可能有警告

	char c[20] = "Hello World!";void* p = c;printf("%s\n", p);

在这里插入图片描述
在这里插入图片描述

3.指针运算

前面我讲了指针的类型,而指针的类型在指针运算中起了关键作用

指针运算主要包括:

  • 指针的解引用
  • 指针 + 整数、指针 - 整数
  • 指针和指针的比较
  • 指针-指针

3.1指针的解引用

指针类型决定了其在解引用时访问几个字节,以及访问的方式

	int n1 = 0x66666666;int n2 = 0x66666666;int n3 = 0x66666666;int* p1 = &n1;*p1 = 0;char* p2 = (char*) & n2;*p2 = 0;float* p3 = (float*) & n3;*p3 = 0;printf("int:%x\nchar:%x\nfloat:%x\n", n1,n2,n3);

在这里插入图片描述

3.2指针 + 整数、指针 - 整数

指针加整数n,其储存的地址加(n* 所指类型的大小),单位字节
可简单验证:

	char ch;int a;int arr[4] = { 0 };char* pc = &ch;int* pa = &a;int(*parr)[4] = &arr;printf("pc=%p\npa=%p\nparr=%p\n", pc, pa, parr);printf("pc=%p\npa=%p\nparr=%p\n", pc+1, pa+1, parr-1);

在这里插入图片描述

3.3指针和指针的比较

在两个指针指向同一块空间的不同位置,我们可以进行指针间的比较:

int arr[10]={1,2,3,4,5,6,7,8,9,10};
int*p1=arr;
int*p2=&arr[9];
while(p1<=p2)
{printf("%d ",*p1);p1++;
}

在这里插入图片描述

3.3指针-指针

相同类型指针可相减,得到相距的元素个数
下面代码使用指针-指针得到字符串长度:

	char ch[10] = "Hahaha";char* pc1 = ch;char* pc2 = ch;while (*pc2 != '\0')pc2++;printf("%d\n", pc2 - pc1);

在这里插入图片描述

希望本篇文章对你有所帮助!
当然,本人仅仅是个C语言初学者,如有任何意见,欢迎各位提出!

C语言指针详解-下

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

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

相关文章

对零基础想转行网络安全同学的一点建议

最近有同学在后台留言&#xff0c;0基础怎么学网络安全&#xff1f;0基础可以转行做网络安全吗&#xff1f;以前也碰到过类似的问题&#xff0c;想了想&#xff0c;今天简单写一下。 我的回答是先了解&#xff0c;再入行。 具体怎么做呢&#xff1f; 首先&#xff0c;你要确…

进程地址空间(二)

目录 前言1. 进程地址空间究竟是什么2. 为什么要有进程地址空间2.1 让进程以统一的视角看待内存结构2. 2 保护物理内存2.3 进程管理 与 内存管理模块 的解耦合2.3.1 页表地址2.3.2 页表的权限管理2.3.3 关于进程挂起 && 惰性加载 4. 进程独立性的体现 前言 接着上篇文…

滑动变阻器的未来发展趋势和前景如何?是否有替代品出现?

滑动变阻器是常见的电子元件&#xff0c;主要用于调节电路中的电阻值。随着科技的不断发展&#xff0c;滑动变阻器的未来发展趋势和前景也引起了广泛关注。 滑动变阻器的未来发展将更加注重智能化&#xff0c;随着物联网、人工智能等技术的快速发展&#xff0c;滑动变阻器也将与…

git stash详细教程

git stash详细教程 基本命令: git stash: 保存当前未提交的更改&#xff0c;并恢复到干净的工作目录。git stash list: 列出所有的 stash。git stash show: 显示最新 stash 的简要内容。git stash show -p: 显示最新 stash 的详细内容。 应用和删除: git stash apply: 应用最新…

华为数通路由交换HCIP/HCNP

2017-2022年软考高级网络规划设计师真题解析视频&#xff01;软考复习一定要多做历年真题&#xff01; 2022年软考网络规划设计师真题解析_哔哩哔哩_bilibili 2024年5月软考网络工程师真题解析合集&#xff0c;考后估分版【综合知识案例分析】 2024年5月软考网络工程师真题解…

C语言 | Leetcode C语言题解之第347题前K个高频元素

题目&#xff1a; 题解&#xff1a; struct hash_table {int key;int val;// 查看 https://troydhanson.github.io/uthash/ 了解更多UT_hash_handle hh; };typedef struct hash_table* hash_ptr;struct pair {int first;int second; };void swap(struct pair* a, struct pair*…

YUM和NFS

文章目录 yum软件仓库的提供方式RPM软件包的来源Linux系统各家厂商用的安装源命令---yum 配置本地yum源具体操作 搭建ftp yum仓库环境具体操作实操环境服务端一、安装 vsftpd服务二、创建一个文件&#xff0c;并且挂载三、开启服务四、查看挂载 客户端五、备份六、搭建ftp yum仓…

【联想电脑】:使用拓展坞后转接HDMI,无法识别显示屏

项目场景&#xff1a; 作为一个嵌入式软件开发者&#xff0c;有两个外接屏幕&#xff0c;不足为奇。 但是在今天的使用电脑过程中&#xff0c;出现了接了一个拓展坞上面有HDMI接口&#xff0c;但是HDMI接口接上外接显示屏的时候电脑无法识别到&#xff0c;导致只有电脑直连的HD…

【Golang】go mod的使用

【1】GO111MODULE有三个值&#xff1a;off, on, auto off&#xff1a;go命令行将不会支持module功能&#xff0c;将会使用旧版本那种通过vendor目录或者GOPATH来查找依赖包的方式。 on&#xff1a;go命令行会使用modules功能&#xff0c;而不…

使用Docker-compose一键部署Wordpress平台

一、Docker-compose概述&#xff1a; docker-compose&#xff1a;单机容器编排 Dockerfile&#xff1a;先配置好文件&#xff0c;然后build&#xff0c;镜像——>容器。 docker-compose&#xff1a;即可基于Dockerfile&#xff0c;也可以基于镜像&#xff0c;可以一键式拉…

安全基础学习-SM4加密算法

SM4 是一种中国国家密码标准(GB/T 32907-2016)中定义的分组加密算法,又称为“中国商用密码算法SM4”。它是由中国国家密码管理局发布的,并广泛应用于金融、电子商务和其他需要数据加密的场景。 1、SM4 算法概述 SM4 是一种对称加密算法,意味着加密和解密使用相同的密钥。…

使用WINUI3 编写一个小软件1 C#

本篇主要是记录安装和运行的问题。 先说安装 因为我是WIN11&#xff0c;所以勾了&#xff0c;如果你是WIN10就不用勾选11那个&#xff0c;但是我不确定用11要不要10那个&#xff0c;所以就勾了&#xff0c;按安装手册来的。 2、创建项目 照着选就完事了&#xff0c;别选错 这…

【数据结构与算法】快速排序

快速排序目录 一.快速排序的原理二.快速排序的图解三.快速排序的实现1.基准两边分2.分而治之 四.完整代码 一.快速排序的原理 每次选取第一个数为基准数.然后使用乾坤大挪移将大于或者小于基准的元素分别放置于基准数两边.继续分别对基准数两侧未排序的数据使用分治法进行处理…

Android回声消除

随着移动互联网的发展&#xff0c;语音通话、语音聊天、互动直播等应用越来越普及&#xff0c;这些应用中的回声问题成为影响用户体验的重要因素之一。回声&#xff0c;即用户在通话过程中听到自己声音的重复&#xff0c;是由于麦克风采集到了扬声器播放出的声音&#xff0c;再…

springboot项目配置https安装ssl证书教程

1.将下载的ssl证书文件中的jks后缀文件放在/src/main/resource文件夹里面 2.在配置文件中&#xff08;yml后缀配置文件的格式不同&#xff09;添加如下配置即可

Postman接口测试项目实战

第 1 章 什么是接口测试 1.1、为什么要进行接口测试 目前除了特别Low的公司外&#xff0c;开发都是前后端分离的&#xff0c;就是说前端有前端的工程师进行编码&#xff0c;后端有后端的工程师进行编码&#xff0c;前后端进行数据基本都是通过接口进行交互的。 1.2、接口测…

IDEA:如何在idea中设置自动导包

这里使用的是idea2020版本,但是不同版本操作不会有较大的差别. 在Editer中展开General之后,选中Auto Import,最后勾选中Add unambiguous imports on the fly.

Java Web|day5.MyBatis

MyBatis 定义 它是一款半自动的ORM持久层框架&#xff0c;具有较高的SQL灵活性&#xff0c;支持高级映射(一对一&#xff0c;一对多)&#xff0c;动态SQL&#xff0c;延迟加载和缓存等特性&#xff0c;但它的数据库无关性较低 **ORM: **Object Relation Mapping&#xff0c;…

培训学校课程管理系统-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

优化深度学习模型:PyTorch中的模型剪枝技术详解

标题&#xff1a;优化深度学习模型&#xff1a;PyTorch中的模型剪枝技术详解 在深度学习领域&#xff0c;模型剪枝是一种提高模型效率和性能的技术。通过剪枝&#xff0c;我们可以去除模型中的冗余权重&#xff0c;从而减少模型的复杂度和提高运算速度&#xff0c;同时保持或甚…