C语言之指针

目录

函数的参数

对象和地址

取地址运算符

注意

指针

注意

指针运算符

注意


在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指向Xiaomingprintf("红红喜欢的人身高:%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.mzph.cn/news/241140.shtml

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

相关文章

十八、本地配置Hive

1、配置MYSQL mysql> alter user rootlocalhost identified by Yang3135989009; Query OK, 0 rows affected (0.00 sec)mysql> grant all on *.* to root%; Query OK, 0 rows affected (0.00 sec)mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)2、…

使用html+css+js+three.js写圣诞树

实现效果&#xff1a; <head><meta charset"UTF-8"><title>Musical Christmas Lights</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"><sty…

网络编程:多进程和多线程编程

1. 多进程编程 1.1 fork #include <sys/types.h> #include <unistd.h> // 调用失败返回 -1 设置 errno pid_t fork( void );子进程返回 0&#xff0c;父进程返回子进程 PID&#xff1b; 信号位图被清除&#xff08;父进程的信号处理函数不再对新进程起作用&…

【网络编程】网络通信基础——简述TCP/IP协议

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、ip地…

sql_lab之sqli中的报错注入,less13

报错注入&#xff08;less-13&#xff09; 正常报错注入&#xff1a; 1.输入用户名和密码123 123显示登录错误 2.输入用户名和密码123’ 123显示登录错误 123后面有’)说明是’)注入 3.查询数据库名 1) and updatexml(<a><b></b></a>,concat(1111…

大数据知识图谱解码:从核心概念到技术实战

文章目录 大数据知识图谱解码&#xff1a;从核心概念到技术实战1. 概述什么是知识图谱知识图谱与自然语言处理的关系 2. 发展历程语义网络本体论大数据时代的知识图谱知识图谱与深度学习的融合 3. 研究内容知识图谱的建模与表示知识抽取知识图谱的融合与对齐知识图谱的推理知识…

KMP入门级别算法详解--终于解决了(next数组详解)

对于正常的字符串模式匹配&#xff0c;主串长度为m&#xff0c;子串为n&#xff0c;时间复杂度会到达O&#xff08;m*n&#xff09;&#xff0c;而如果用KMP算法&#xff0c;复杂度将会减少线型时间O&#xff08;mn&#xff09;。 设主串为ptr"ababaaababaa";&#…

Prometheus介绍和安装

Prometheus介绍和安装 1. Prometheus介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云…

P4 音频知识点——PCM音频原始数据

目录 前言 01 PCM音频原始数据 1.1 频率 1.2 振幅&#xff1a; 1.3 比特率 1.4 采样 1.5 量化 1.6 编码 02. PCM数据有以下重要的参数&#xff1a; 采样率&#xff1a; 采集深度 通道数 ​​​​​​​ PCM比特率 ​​​​​​​ PCM文件大小计算&#xff1a; ​…

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解 题目本身不难想 首先注意到所有查询的序列长度都是小于logn级别的 我们可以枚举序列长度len&#xff0c;然后用类似滑动窗口的方法&#xff0c;一次性预处理出每种字串的所有出现位置&#xff0c;也就是开N个set去维护所有的位置。预处理会进行O(logn)轮&#xff0c;每…

KubeSphere金丝雀发布流量分布调节不生效(将所有流量按比例分配给灰度发布版本)

如题 金丝雀发布按照流量比例访问不能生效 1、自制应用生成的路由添加注释: nginx.ingress.kubernetes.io/service-upstream:"true" 2、项目网关开启 3、完成 以上&#xff0c;祝好。

Tomcat远程调试

windows环境 写一个 startup-debug.bat&#xff0c;指定tomcat的根目录&#xff0c;端口自己定义 rem *******设置Tomcat目录*******-- set CATALINE_HOMED:\asd\A8-2\tomcat d: rem 8787为可用端口,为远程调试监听端口-- cd %CATALINE_HOME%/bin set JPDA_ADDRESS8787 set J…

Leetcode—445.两数相加II【中等】

2023每日刷题&#xff08;六十七&#xff09; Leetcode—445.两数相加II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2…

一个简单的 HTTP 请求和响应服务——httpbin

拉取镜像 docker pull kennethreitz/httpbin:latest 查看本地是否存在存在镜像 docker images | grep kennethreitz/httpbin:latest 创建 deployment&#xff0c;指定镜像 apiVersion: apps/v1 kind: Deployment metadata:labels:app: httpbinname: mm-httpbinnamespace: mm-…

Latex生成的PDF中加入书签/Navigation/导航

本文参考&#xff1a;【Latex学习】在生成pdf中加入书签/目录/提纲_latex 书签-CSDN博客 &#xff08;这篇文章写的真的太棒了&#xff01;非常推荐&#xff09; 题外话&#xff0c;我的碎碎念&#xff0c;这也是我如何提高搜索能力的办法&#xff1a;想在Latex生成的PDF中加入…

2023的AI工具集合,google和claude被禁用解决和edge的copilot

一、前言 AI工具集合 首先&#xff0c;OpenAI的ChatGPT以其深度学习模型和强大的语言处理能力引领了AI聊天机器人的潮流。自2022年11月30日上线以来&#xff0c;它创下了100万用户的注册记录&#xff0c;并被广泛应用于全球财富500强公司。为了实现盈利&#xff0c;OpenAI发布…

iOS 开发设计 App 上架符合要求的截图

1. 真机运行截屏 2. 可以在 Apple developer 官网 Design 下找到 iPhone 边框 https://developer.apple.com/design/resources/ 不用这个边框也行&#xff0c;可以参考已上架 App 的图片框 3. 使用 Procreate&#xff08;PhotoShop&#xff09;创建符合要求的画布大小 4. 导入…

springboot集成websocket全全全!!!

一、界面展示 二、前置了解 1.什么是websocket WebSocket是一种在单个TCP连接上进行全双工通信的持久化协议。 全双工协议就是客户端可以给我们服务器发数据 服务器也可以主动给客户端发数据。 2.为什么有了http协议 还要websocket 协议 http协议是一种无状态&#xff0c;非…

铭飞CMS cms/content/list接口存在SQL注入 附POC

@[toc] 铭飞CMS cms/content/list接口存在SQL注入 附POC 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用…

内存函数的学习

额外知识点 第一个 假设c为int类型&#xff0c;&#xff08;char&#xff09;c之后&#xff0c;之后如果还用变量c的话&#xff0c;c依然为int类型。&#xff08;&#xff09;强制转换操作符并不会永久改变原本的变量类型。 第二个 \0在打印时不会显示出来 第三个 void …