C语言二刷指针篇
&取得变量的地址
printf("%p\n", &a);
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &a[1]);
前三个输出相同,a[0]和a[1]之间相差4
指针就是保存地址的变量,指针里放的是别的变量的地址
p指向i代表p里面的值就是i变量的地址
int *p,q;//*p是int类型
int* p,q;//q是int类型
对于函数:
void f(int *p);
在被调用的时候得到了某个变量的指针:
int i=0;f(&i);
在函数里面可以通过这个指针访问到外面的这个i
如何通过指针访问和操作变量
#include<stdio.h>void f(int* p);
void g(int k);int main() {int i = 6;printf("&i=%p\n", &i);f(&i);g(i);return 0;
}void f(int* p) {printf("p=%p\n", p);printf("*p=%d\n", *p);
}
void g(int k) {printf("k=%d\n", k);
}
上面的代码中,printf("&i=%p\n", &i);用于输出变量i的地址,以便观察变量i在内存中的存储位置。%p是格式化输出符号,用于输出指针(地址)类型的值。
f(&i);调用f函数,并将i的地址作为参数传递给f函数。这样f函数就可以通过指针操作来访问和修改i的值(虽然在这个f函数中没有修改i的值)。
g(i);调用g函数,并将i的值(而不是地址)作为参数传递给g函数。这样g函数会得到i的一个副本,对这个副本的任何操作都不会影响main函数中的i。
f函数接受一个整型指针p作为参数,被初始化为i的地址。
printf("p=%p\n", p);输出指针p的值,也就是i的地址。这与在main函数中输出的&i的值应该是相同的。
printf("*p=%d\n", *p);输出指针p所指向的内存位置的值。由于p指向i,所以这里输出的就是i的值,即6。
&i=000000034277F9F4p=000000034277F9F4
*p=6k=6
修改上面的代码:
#include<stdio.h>void f(int* p);
void g(int k);int main() {int i = 6;printf("&i=%p\n", &i);f(&i);g(i);return 0;
}void f(int* p) {printf("p=%p\n", p);printf("*p=%d\n", *p);*p = 26;
}
void g(int k) {printf("k=%d\n", k);
}
如果在f函数定义时将*p修改为26,那么最后k的值也会是26。
指针的使用
场景一:
交换两个变量
#include<stdio.h>void swap(int* pa, int* pb);int main() {int a = 5;int b = 6;swap(&a, &b);printf("a=%d,b=%d\n",a,b);return 0;
}
void swap(int* pa, int* pb) {int t = *pa;*pa = *pb;*pb = t;
}
场景二:
- 函数返回多个值,某些值就只能通过指针返回
- 传入的参数实际上是需要保存带回的结果的变量
#include <stdio.h>// 这个函数通过指针返回两个值,一个是两个数的和,一个是两个数的乘积
void cal(int num1, int num2, int* sum, int* product) {*sum = num1 + num2;*product = num1 * num2;
}int main() {int num1 = 5;int num2 = 3;int sum_result, product_result;cal(num1, num2, &sum_result, &product_result);printf("The sum of %d and %d is %d\n", num1, num2, sum_result);printf("The product of %d and %d is %d\n", num1, num2, product_result);return 0;
}
在cal函数中sum和product是指针类型的,在main函数中sum和product是整数类型的。
- 函数返回运算的状态,结果通过指针返回
- 常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:-1和0
- 但是当任何数值都是有效的可能结果时,就得分开返回
#include<stdio.h>int divide(int a, int b, int* result) {int ret = 1;if (b == 0)ret = 0;else {*result = a / b;}return ret;
}int main(void) {int a = 5;int b = 2;int c;if (divide(a, b, &c)) {printf("%d/%d=%d\n", a, b, c);}return 0;
}
上面的代码中通过指针将除法结果返回给调用者,并使用函数返回值表示运算是否成功,这种方式在处理可能出现错误的运算时比较常用。
常见错误:
指针在得到地址前不能被赋值(除了NULL),因为此时被赋的值是一个未知的地址。
如果一个指针没有被初始化(即没有被赋予一个有效的地址)就进行解引用赋值操作会导致未定义行为。
int *ptr;
*ptr = 10; // 错误,ptr未初始化,其值是不确定的,此时进行解引用赋值可能导致程序崩溃或产生不可预测的结果
指针可以被赋予NULL值,这是一种特殊的赋值,表示指针不指向任何有效的内存地址。
int *ptr = NULL;
当要给指针赋予一个有意义的值时,这个值应该是一个已经合法分配内存的地址,比如通过malloc等内存分配函数获得的地址,或者是某个已存在变量的地址。
int num = 5;
int *ptr = # // 正确,将指针ptr指向变量num的地址
从这个意义上说,不能随意将指针指向一个未知的地址,但可以将其初始化为`NULL`或者在确保地址合法性的情况下进行赋值。
指针和数组
数组变量接收数组接收到的是值(普通变量),指针的值(指针)
函数参数表中的数组实际上就是指针。
以下四种函数原型是等价的:
int sum(int *ar,int n);
int sum(int *,int);
int sum(int ar[],int n);
int sum(int [],int);
数组变量是特殊的指针
数组变量本身表达地址
int a[10];
int *p=a;//无需用&取地址
但是数组的单元表达的是变量,需要用&取地址,a==&a[0]
[]运算符可以对数组做,也可以对指针做:p[0]<==>*p
数组变量是const的指针,所以不能被赋值
指针与const
指针是const
表示一旦得到了某个变量的地址,不能再指向其他变量
int * const q = &i;//q是const
*q=26;//ok
q++;//error
比如上面的代码,q只能指向i的事实不能被改变,指针不能指向别人,指针不能被修改
所指是const
表示不能通过这个指针去修改那个变量(并不能使那个变量成为const)
const int *p=&i;
*p=26;//error(*p是const)
i=26;//ok
p=&j;//ok
i和p可以变,i可以被赋予其他值,p可以指向其他地址,但是通过p去修改i就不可以(*p是个常量),变量不能通过该指针改变
总结:const在前,不能改值;const在后,不能改地址
转换:总是可以把一个非const的值转换成const的
void f(const int* x);
int a=15;
f(&a);//ok
const int b=a;
f(&b);//ok
b=a+1;//Error!
当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改
const数组
const int a []={1,2,3,4,5,6};
数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int,所以必须通过初始化进行赋值
如果要保护数组不被函数破坏(修改数组的值),可以设置参数为const
int sum(const int a[], int length)
指针运算
char ac[] = { 0,1,2,3 };char* p = ac;printf("p =%p\n", p);printf("p+1=%p\n", p+1);printf("*(p+1) =%d\n", *(p+1));char ai[] = { 0,1,2,3 };char* q = ai;printf("q =%p\n", q);printf("q+1 =%p\n", q+1);printf("*(q+1) =%d\n", *(q+1));
输出:
p =0000008CB1AFFA44
p+1=0000008CB1AFFA45
*(p+1) =1
q =0000008CB1AFFA84
q+1 =0000008CB1AFFA85
*(q+1) =1
上面代码中,指针加1表示让指针指向下一个变量。如果指针不是一片连续的分配空间,如数组,则这种运算没有意义。
用指针做什么:
- 需要传入较大的数据时用参数
- 传入数组后对数组做操作
- 函数返回不止一个结果
- 需要用函数来修改不止一个变量
- 动态申请的内存
动态内存分配
在程序运行期间根据实际需要来分配和释放内存空间的一种机制。
现在根据用户输入的元素数量动态分配内存来存储一个整数数组,然后从用户获取数组元素的值
#include<stdio.h>
#include<stdlib.h>
int main() {int number;int* a;int i;printf("输入数量:");scanf("%d", &number);a = (int*)malloc(number * sizeof(int));for (i = 0; i < number; i++) {scanf("%d", &a[i]);}for (i = number - 1; i>=0; i++) {printf("%d ", a[i]);}free(a);return 0;
}
相关文章:
C语言二刷指针篇
&取得变量的地址 printf("%p\n", &a); printf("%p\n", a); printf("%p\n", &a[0]); printf("%p\n", &a[1]); 前三个输出相同,a[0]和a[1]之间相差4 指针就是保存地址的变量,指针里放的是别的…...
LeetCode题练习与总结:回文对--336
一、题目描述 给定一个由唯一字符串构成的 0 索引 数组 words 。 回文对 是一对整数 (i, j) ,满足以下条件: 0 < i, j < words.length,i ! j ,并且words[i] words[j](两个字符串的连接)是一个回文…...
CesiumJS 案例 P7:添加指定长宽的图片图层(原点分别为图片图层的中心点、左上角顶点、右上角顶点、左下角顶点、右下角顶点)
CesiumJS CesiumJS API:https://cesium.com/learn/cesiumjs/ref-doc/index.html CesiumJS 是一个开源的 JavaScript 库,它用于在网页中创建和控制 3D 地球仪(地图) 一、添加指定长宽的图片图层(原点为图片图层的中心…...
Redis 主从同步 问题
前言 相关系列 《Redis & 目录》(持续更新)《Redis & 主从同步 & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Redis & 主从同步 & 总结》(学习总结/最新最准/持续更新)《Redis &a…...
【SQL Server】探讨 IN 和 EXISTS之间的区别
前言 在使用 SQL 查询相关表数据时,通常需要根据另一个表中的值来筛选数据。而 IN 与 EXISTS 子句都是用于此场景的常用方式,但使用时两者存在工作方式不同。它们使用上的选择会显著影响查询的性能,尤其是在大型数据集中。本文我们一起探讨 IN 和 EXISTS 之间的区别、使用与…...
清理pip和conda缓存
当用户目录没有空间时,可清理pip和conda缓存 清理conda缓存: conda clean --all清理pip缓存: pip cache purgeNote: 可以利用软链接,将用户目录下的文件链接到其他位置 首先移动文件或文件夹到其他位置 mv ~/test /…...
git rebase和merge的区别
Git merge和Git rebase是两种不同的合并策略,它们在处理分支合并时有各自的优点和缺点。 Git fetch git fetch 命令用于从远程仓库获取最新的更改,但不会自动合并这些更改到你的本地分支。它会下载远程仓库的所有分支和标签,并更新你的本地…...
【elkb】linux麒麟v10安装ELKB 8.8.X版本(ARM架构)
下载软件 相关版本信息 elasticsearch:8.8.1kibana:8.8.1logstash:8.8.1filebeat:8.8.1 下载地址 https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.1-linux-aarch64.tar.gzhttps://artifacts.elastic…...
bluez hid host介绍,连接键盘/鼠标/手柄不是梦,安排
零. 前言 由于Bluez的介绍文档有限,以及对Linux 系统/驱动概念、D-Bus 通信和蓝牙协议都有要求,加上网络上其实没有一个完整的介绍Bluez系列的文档,所以不管是蓝牙初学者还是蓝牙从业人员,都有不小的难度,学习曲线也相对较陡,所以我有了这个想法,专门对Bluez做一个系统…...
GPT打数模——电商品类货量预测及品类分仓规划
背景 电商企业在各区域的商品存储主要由多个仓库组成的仓群承担。其中存储的商品主要按照属性(品类、件型等)进行划分和打标,便于进行库存管理。图 1 是一个简化的示意图,商品品类各异,件数众多,必须将这些…...
华为OD机试 - 螺旋数字矩阵 - 矩阵(Python/JS/C/C++ 2024 D卷 100分)
华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,…...
分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB)
分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB) 目录 分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB)分类效果基本介绍程序设计参考资料分类效果 基本介绍 GCN图卷积神经网络多特征分类预测(MATLAB) 在图卷积神经网络(GCN)中,多特征分类...
FPGA搭建PCIE3.0通信架构简单读写测试,基于XDMA中断模式,提供3套工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博客方案的PCIE2.0版本 3、PCIE基础知识4、工程详细设计方案工程设计原理框图XDMA配置及使用XDMA中断模块数据缓存架构用户逻辑Windows版本XDMA驱动安装Linux版本XDMA驱动安装测试应用程序工程源码架构PCIE上板…...
App相关技术以及打包
平时小伙伴们自己的博客网站只能在浏览器打开,但是有时候你想要制作自己独立个人博客app,宣传并推广自己的app,打造个人ip。如何把自己的web博客网站打包成安卓app? 1.开发App的相关技术使⽤ ⽬前市⾯上的移动互联开发技术主要分…...
【unity】【游戏开发】Unity代码不给提示怎么办?
【现象】 Unity用着用着忽然VS脚本不给提示了。 【分析】 重启Unity无效 重启VS无效 重装VS无效 感觉应该是项目设置问题 【最终方法】 打开Edit->Preferences。 如果是这个画面就把Script Editor改成自己的VS编辑器。 变成下面这个样子,点击Regenerate Pr…...
Kubernetes固定Pod IP和Mac地址
方案1: 在 Calico GitHub Issues#5196 问题的 commits#6249 提交中,引入新的 Pod 注释cni.projectcalico.org/hwAddr,用于将指定的 MAC 地址分配给容器端 Veth 接口。 将Calico升级至v3.24.1或以上版本,使用如下注解轻松设置Pod…...
计算机组成原理之数据的对齐和大/小端存放方式、计算机中数据对齐的具体方式有哪些
1、计算机组成原理之数据的对齐和大/小端存放方式 数据对齐 数据对齐是处理器为了提高处理性能而对存取数据的起始地址所提出的一种要求。 系统一次性读取内存中数据的大小是固定的,例如字长为32位的操作系统,默认的一次读取4字节内容。因此ÿ…...
【学术论文投稿】Windows11开发指南:打造卓越应用的必备攻略
【IEEE出版南方科技大学】第十一届电气工程与自动化国际会议(IFEEA 2024)_艾思科蓝_学术一站式服务平台 更多学术会议论文投稿请看:https://ais.cn/u/nuyAF3 目录 引言 一、Windows11开发环境搭建 二、Windows11关键新特性 三、Windows11设计指南 …...
【毕业论文+源码】基于SSM(Spring + Spring MVC + MyBatis)的房屋租赁系统
创建一个基于SSM(Spring Spring MVC MyBatis)框架的房屋租赁系统是一个涉及多个步骤的过程。这个过程包括但不限于需求分析、数据库设计、前端界面设计以及后端逻辑实现等。 1. 需求分析 首先,明确你的房屋租赁系统的功能需求。例如&…...
【golang】解析 JSON到指定结构体
1.解析[1,2,3,4]数组类型的json package mainimport ("encoding/json""fmt" )func main() {// JSON 数据jsonData : [1, 2, 3, 4]// 定义一个切片来接收解析后的数据var numbers []int// 解析 JSON 数据到切片err : json.Unmarshal([]byte(jsonData), &am…...
设计模式——过滤器模式
一、定义和概念 定义 C 过滤器模式(Filter Pattern)也称为标准模式(Criteria Pattern),是一种设计模式,用于根据不同的标准或条件从一组对象中筛选出符合条件的对象。它将筛选条件的逻辑封装在不同的过滤器…...
Unity(四十八):Unity与Web双向交互
效果 游戏对象绑定脚本 游戏脚本源码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Tent : MonoBehaviour {public Camera camera;// Start is called before the first frame updatevoid Start(){}// Update is called once…...
web前端--网页练习
html代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>小米</title><!-- 引…...
信息安全入门——网络安全控制
目录 前言信息安全入门:网络安全控制基础1. 用户识别技术:确认你是谁2. 访问控制技术:定义你能做什么3. 访问控制列表(ACL):精细的权限管理4. 漏洞控制:防范未然5. 入侵检测系统(IDS…...
跟着鸟儿学飞行?扑翼机器人的感知秘籍
大家好!今天来了解一篇扑翼机器人的研究——《Avian-inspired embodied perception in biohybrid flapping-wing robotics》发表于《Nature Communications》。在广阔天空中,鸟类凭借精妙翅膀结构与敏锐感知自由翱翔,这一直吸引着科学家探索其…...
Python画笔案例-093 绘制 彩虹图
1、绘制 彩虹图 通过 python 的turtle 库绘制 彩虹图,如下图: 2、实现代码 绘制 彩虹图,以下为实现代码: """彩虹图.py """ import turtledef draw_semi_circle(radius):"""画半圆函数"""turtle...
【数据结构】贪心算法:决策的艺术
贪心算法(Greedy Algorithm)是一类在每一步选择中都采取局部最优解的方法,希望最终能够达到全局最优解。通俗地说,贪心算法的思想就是“每一步都尽量做出最好的选择”,以期望整个过程的最终结果也达到最优状态。贪心算…...
Linux LVS详解
LVS(Linux Virtual Server)即Linux虚拟服务器,是一个基于Linux操作系统的高性能、可扩展的负载均衡器。以下是对LVS的详细介绍: 一、简介 LVS项目由章文嵩博士在1998年5月发起,是中国国内最早出现的自由软件项目之一…...
LabVIEW显微镜自动对焦系统
在生物医学研究中,显微镜图像的清晰度对于细胞分析非常重要。传统的手动对焦方法容易受到人为因素的影响,因此开发了一种自动对焦技术,以提高图像采集的准确性和效率。 自动对焦方法概述 该系统结合了图像清晰度评估和一维功能优化ÿ…...
基于IP的真实地址生成器
ip-geoaddress-generator 是一个基于 Web 的在线应用程序,能够根据 IP 地址生成真实的随机地址信息。通过多个 API 获取位置数据和随机用户信息,该工具为用户提供了完整的虚拟身份。它由 Next.js 和 Radix UI 构建,具备自动检测当前 IP 地址和…...
深圳旅游网站建设/seo网络优化师就业前景
我们通常会用屏(Screen)来称呼一个页面(Page),一个完整的App应该是有多个Page组成的。 在之前的案例(豆瓣)中,我们通过IndexedStack来管理了首页中的Page切换: 首页-书影…...
手机凡客网/优化电池充电什么意思
原文地址:php代码审计之函数缺陷syst1m.comin_array函数缺陷Wish ListCodeclass Challenge {const UPLOAD_DIRECTORY ./solutions/;private $file;private $whitelist;public function __construct($file) {$this->file $file;$this->whitelist range(1,…...
房屋产权地址备案在那个网站做/企业培训公司有哪些
第一次观看我文章的朋友,可以关注、点赞、转发一下,每天分享各种干货技术和程序猿趣事 前言 职场的金三银四跳槽季又来了,不同的是今年比往年「冷」一些,形式更加严峻一些,大家多多少少可能都听到或看到一些信息&…...
怎样用dw做网站主页/目前病毒的最新情况
seq2seq模型目前还有很多缺点,本文所做实验表明: (1)生成的文本过短,3%的摘要不超过3个词 (2)随着生成序列的增加,生成性能急剧恶化 (3)重复生成某个词 &…...
域名有wordpress/应用商店下载安装
不同SD记忆卡厂商及品牌的记忆卡之实际传输速度有時會有很大差异。对影片录像来说需要非常高稳定的最小写入速度,因此各式各样不同写入速度的记忆卡,让人难以决定该选择哪一张卡,才能确保播放顺畅。因此,SD协会将速度等级规格&…...
免费发布信息平台网/搜索引擎优化与推广技术
当前,区块链被视为新一代互联网的底层技术,并逐渐应用到金融、物流、传媒等领域。在应用的过程中,区块链网络的运行与维护对算力的要求也越来越高,如今北京市正在建设的区块链算力平台就是支撑区块链场景应用的重要基建之一。 什…...