C语言之指针

news2025/1/18 18:04:38

目录

函数的参数

对象和地址

取地址运算符

注意

指针

注意

指针运算符

注意


在C语言中,指针是一个十分重要的概念,它的作用是“指示对象”。

例如:你要去一座公寓楼找一位朋友,公寓楼由很多楼层组成,每个楼层由若干个房间组成,而房间都有属于一个自己的编号,假如你不知对应的楼层的房间号,你需要一个一个房间去找,这是很麻烦的,而当你指定对应的房号时就能快速精准定位目标,而这里的房间号就对应为地址,也可以称为指针。


下面我们由一个例子来引出接下来我们所要学习的关于指针的基本知识:

函数的参数

#include<stdio.h>

/*将n1和n2的和、差分别保存在sum、diff中(错误的示范)*/
void sum_diff(int n1, int n2, int sum, int diff)
{
	sum = n1 + n2;
	diff = (n1 - n2) ? n1 - n1:n2 - n1;
}
int main()
{
	int na, nb;
	int wa = 0, sa = 0;
	
	puts("请输入两个整数:");
	printf("整数A:");scanf("%d", &na);
	printf("整数B:");scanf("%d", &nb);

	sum_diff(na, nb, wa, sa);
	
	printf("两数之和是%d,两数之差是%d", wa, sa);
	
	return 0;
}

main函数在调用sum_diff函数时,实参na,nb,wa,sa的值会分别传递给形参n1,n2,sum,diff。这个复制的过程是单向的,这中参数传递方式称为值传递,这样即使改变形参sum,diff的值原来的wa,sa的值并不会改变。

因此在调用sum_diff函数之后,在main函数中wa,sa的值依然是0.

在前面的学习中,我们可以得知,函数返回到调用源的返回值只能有1个,不能返回到两个以上的值,所以不能将和、差返回给函数。

为了解决这个问题,必须掌握C语言学习的难点之一——指针(pointer)


对象和地址

变量是“保存数值的盒子”,它并不是像下图中随意存放的:

而是下面这样有序的存放在内存空间里:

变量具有多个侧面或者是属性,举例来说,其中一个属性就是数据类型长度,上面中的int型和double型的数据长度就不同,这两个变量的长度可以通过sizeof()求得。

有些编译器中sizeof(int)、sizeof(double)是相等的,但是构成它们的每一位却不尽相同

 数据类型决定变量可以表示数值范围,除此之外,表示变量在内存中生命期范围的存储期以及变量名也都是变量的重要属性。

在广阔的内存空间上,存在着很多对象,这就需要某种方式来表示各个对象在内存中存储的位置,这就是地址(address)

对象(变量)的地址是指其在内存中的存储编号,其中int型变量n的地址为212,double型变量x的地址为216。


取地址运算符

每个对象都有地址,那么我们来看下它们的地址是怎样的:

#include<stdio.h>

int main()
{
	int    n;
	double x;
	int  a[3];
    printf("n的地址:%p\n", &n);      
	printf("x的地址:%p\n", &x);
	printf("a[0]的地址:%p\n", &a[0]);
	printf("a[1]的地址:%p\n", &a[1]);
	printf("a[2]的地址:%p\n", &a[2]);

	return 0;
}
/*n的地址:0061FECC
x的地址:0061FEC0
a[0]的地址:0061FEB4
a[1]的地址:0061FEB8
a[2]的地址:0061FEBC*/

对象的地址通常都是由十六进制数表示的,但是在不同的编译器下,有时结果也不相同。

我们一直使用的单目运算符&通常被称为取地址运算符(address operator),将&写在对象名之前就可以得到该对象的地址。

如果对象的长度为2,占用212号和213号的内存单元,那么该对象的地址就是它的首地址212号。

取地址运算符
  &a                                                       取得a的地址(生成指向a的指针)

注意

取地址运算符&的功能是取得对象的地址,表示对象地址的转换说明为%p(p为pointer的首字母)。


指针

只显示地址并无意思,让我来看看更具实际作用的功能吧:

#include<stdio.h>

int main()
{
	int Lihua = 178;//李华的身高
	int Wangjun = 175;//王军的身高
	int Xiaoming = 179;//小明的身高
	
	int *honghong, *huahua;//红红、花花
	
	honghong = &Lihua;//honghong指向Lihua(喜欢李华)
	huahua = &Xiaoming;//huahua指向Xiaoming
	
	printf("红红喜欢的人身高:%d\n", *honghong);
	printf("花花喜欢的人身高:%d\n", *huahua);

	honghong = &Wangjun;//honghong指向Wangjun(移情别恋)
	
	*huahua = 180;//将huahua指向的对象赋值为180(修改花花喜欢的人身高)
	
	putchar('\n');
	printf("李华的身高是:%d\n", Lihua );
	printf("王军的身高是:%d\n", Wangjun );
	printf("小明的身高是:%d\n", Xiaoming );
	printf("红红喜欢的人的身高是:%d\n", *honghong);
	printf("花花喜欢的人的身高是:%d\n", *huahua);
	
	return 0;
}

变量honghong和huahua的声明中,变量名前带有 * ,通过该声明定义了两个“指向int型变量的指针变量”,它们指向的是int型对象

我首先明确一下“int型变量”和“指向int型变量的指针变量”有何区别:

☛int型变量:保存“整数”盒子

☛指向int型变量的指针变量:保存“存放整数对象的地址”的盒子

我们以下图为例:

int型Lihua的地址是212号,因此若执行“honghong = &Lihua”,honghong中就会被存入212号,这是honghong和Lihua的关系就是honghong指向lihua

当指针p的值为对象x的地址时,一般说“p”指向“x”。

honghong的数据类型是“指向int型变量的指针型”

honghong = &Lihua;

&Lihua的类型也是“指向int型变量的指针”,取地址运算符与其说时取得地址,不如说是生成指针。

表达式&Lihua是指向Lihua的指针,其值为Lihua的地址。

注意

将取地址运算符&写在Type型对象x前得到的&x为Type *指针,其值为x的地址。


指针运算符

在进行显示的地方,就要用到指针运算符(也称为间接访问运算符)的单目运算符 * (unary operator)。将指针运算符*写于指针之前,就可以显示该指针指向的对象内容。

指针运算符
*a                                          a指向的对象
#include<stdio.h>

int main()
{
	int a = 10;
	int *pa = &a; 
	*pa = 20;	
	
	printf("%d", a);
	return 0;
}

在这里*pa就存放变量a的地址,就相当于“pa指向的对象”,因此*pa就是变量a的别名,所以改动*pa存放地址的值,也就相当于改动了a的值。

注意

当pa指向a时,*pa就是变量a的别名。


指针在C语言中是十分重要的,但是不难理解:指针就相当于一个门牌号方便与从内存单元中查找,而形如int *a;的形式 *a指的是指针型变量,而加上int就是创造了一个保存对象地址的变量,而取得地址的指针型变量就相当于该地址所在变量的分身。

相信大家只要用心梳理几遍就可以明了了。在下面的学习中我们还将会学习关于函数、数组与指针的关系。

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

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

相关文章

MySQL中CASE when 实战

CASE 语法 CASEWHEN condition1 THEN result1WHEN condition2 THEN result2WHEN conditionN THEN resultNELSE result END; 将表中的内容转换为右边的形式&#xff1a; 1、创建表&#xff0c;创建数据 CREATE TABLEchapter10_7 (order_id VARCHAR(255) NULL,price VARCHAR(25…

【Linux驱动】字符设备驱动程序框架 | LED驱动

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;Hello驱动程序⚽驱动程序框架⚽编程 &#x1f3c0;LED驱动⚽配置GPIO⚽编程驱动…

NHNL因子如何刻画行业强弱

根据华福证券-市场情绪指标专题&#xff08;五&#xff09;&#xff0c;进行了提炼和改写&#xff0c;特此致谢&#xff01; ( N H N L ) % ( c o u n t ( H H V ) − c o u n t ( L L V ) ) / N (NHNL)\% (count(HHV) - count(LLV))/N (NHNL)%(count(HHV)−count(LLV))/N 个…

Uniapp + Vue3 + Pinia + Vant3 框架搭建

现在越来越多项目都偏向于Vue3开发&#xff0c;想着uniapp搭配Vue3试试效果怎么样&#xff0c;接下来就是详细操作步骤。 初始化Uniapp Vue3项目 App.vue setup语法 <script setup>import {onLaunch,onShow,onHide} from dcloudio/uni-apponLaunch(() > {console.l…

Linux poll 和 select 机制

poll select 介绍 使用非阻塞 I/O 的应用程序常常使用 poll, select, 和 epoll 系统调用. poll, select 和 epoll 本质上有相同的功能: 每个允许一个进程来决定它是否可读或者写一个 或多个文件而不阻塞. 这些调用也可阻塞进程直到任何一个给定集合的文件描述符可用来 读或写.…

叮咚,微信年度聊天报告(圣诞节版)请查收~丨GitHub star 16.8k+

微信年度聊天报告——圣诞节特别版&#xff0c;快发给心仪的ta吧~ 开源地址 GitHub开源地址&#xff1a;https://github.com/LC044/WeChatMsg 我深信有意义的不是微信&#xff0c;而是隐藏在对话框背后的一个个深刻故事。未来&#xff0c;每个人都能拥有AI的陪伴&#xff0c;…

「Vue3面试系列」Vue3.0性能提升主要是通过哪几方面体现的?

文章目录 一、编译阶段diff算法优化静态提升事件监听缓存SSR优化 二、源码体积三、响应式系统参考文献 一、编译阶段 回顾Vue2&#xff0c;我们知道每个组件实例都对应一个 watcher 实例&#xff0c;它会在组件渲染的过程中把用到的数据property记录为依赖&#xff0c;当依赖发…

显卡之争!英伟达和AMD下场互掐!GPU霸主地位是否能保?

大家好&#xff0c;我是二狗。 英伟达和AMD这两家芯片巨头掐起来啦&#xff01; 事情的起因是&#xff0c;两周前AMD董事会主席兼CEO苏姿丰在一场活动中发布了用于生成式AI和数据中心的新一代Intinct MI300X GPU芯片加速卡。 单单发布显卡没啥问题&#xff0c;但是AMD声称MI300…

【Spring实战】03 JDBC常用操作

文章目录 1. JdbcTemplate 类1&#xff09;queryForList2&#xff09;update3&#xff09;query4&#xff09;execute5&#xff09;queryForObject 2.代码及执行1&#xff09;代码2&#xff09;执行 3. 优点4. 详细代码总结 Spring JDBC 是 Spring 框架提供的一种用于简化数据库…

05. Springboot admin集成Actuator(一)

目录 1、前言 2、Actuator监控端点 2.1、健康检查 2.2、信息端点 2.3、环境信息 2.4、度量指标 2.5、日志文件查看 2.6、追踪信息 2.7、Beans信息 2.8、Mappings信息 3、快速使用 2.1、添加依赖 2.2、添加配置文件 2.3、启动程序 4、自定义端点Endpoint 5、自定…

基于epoll的web服务器(C语言版本)

基于epoll的web服务器(C语言版本) 1. 初始化监听套接字 包括创建监听套接字&#xff0c;设置端口复用&#xff0c;绑定&#xff0c;设置监听等步骤 1.1 创建监听套接字&#xff08;socket函数&#xff09; socket()打开一个网络通讯端口&#xff0c;如果成功的话&#xff0…

界面控件DevExpress v23.2全新发布 - 官宣正式支持.NET 8

DevExpress拥有.NET开发需要的所有平台控件&#xff0c;包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress 今年第一个重要版本v23.1正式发布&#xff0c;该版本拥有众多…

【精选】vulnhub CTF6 linux udev提权 (青铜门笔记)

一、信息收集 1.主机探测 发现靶机的IP地址是&#xff1a;192.168.103.130 ┌──(root&#x1f480;kali)-[~] └─# arp-scan -l2.访问web页面 发现有个登录的页面&#xff0c;尝试了弱口令&#xff0c;但是发现没有成功&#xff1b; 所以&#xff0c;我们需要在后面的信…

单词接龙[中等]

一、题目 字典wordList中从单词beginWord和endWord的 转换序列 是一个按下述规格形成的序列beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 1、每一对相邻的单词只差一个字母。 2、对于1 < i < k时&#xff0c;每个si都在wordList中。注意&#xff0c;beg…

数值分析期末复习

第一章 科学计算 误差 解题步骤 先求绝对误差: ∣ x − x ∗ ∣ |x - x^*| ∣x−x∗∣求相对误差限: ∣ x − x ∗ ∣ x ∗ \frac{|x\,\,-\,\,x^*|}{x^*} x∗∣x−x∗∣​求有效数字 ∣ x − x ∗ ∣ 需要小于它自身的半个单位 |x-x^*|\text{需要小于它自身的半个单位} ∣…

Kafka集群架构原理(待完善)

kafka在zookeeper数据结构 controller选举 客户端同时往zookeeper写入, 第一个写入成功(临时节点), 成为leader, 当leader挂掉, 临时节点被移除, 监听机制监听下线,重新竞争leader, 客户端也能监听最新leader leader partition自平衡 leader不均匀时, 造成某个节点压力过大, …

数字信号的理解

1 数字信号处理简介 数字信号处理 digital signal processing&#xff08;DSP&#xff09;经常与实际的数字系统相混淆。这两个术语都暗示了不同的概念。数字信号处理在本质上比实际的数字系统稍微抽象一些。数字系统是涉及的硬件、二进制代码或数字域。这两个术语之间的普遍混…

物联网产品设计,聊聊设备OTA的升级

物联网产品设计部分的OTA设备固件是一个非常重要的部分&#xff0c;能够实现升级用户服务、保障系统安全等功能。 在迅速变化和发展的物联网市场&#xff0c;新的产品需求不断涌现&#xff0c;因此对于智能硬件设备的更新需求就变得空前高涨&#xff0c;设备不再像传统设备一样…

SQL分类

SQL分类 DDL 查询库 查询表 创建表 修改表 DML 添加数据 修改数据 删除数据 DQL 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查询 执行顺序 DCL 管理用户 管理权限 数据类型 数值类型 字符串类型 日期类型

从零构建tomcat环境

一、官网构建 1.1 下载 一般来说对于开源软件都有自己的官方网站&#xff0c;并且会附上使用文档以及一些特性和二次构建的方法&#xff0c;那么我们首先的话需要从官网或者tomcat上下载到我们需要的源码包。下载地址&#xff1a;官网、Github。 这里需要声明一下&#xff…