关于在c++中使用数组名作为函数参数,或者使用数组名的地址作为函数参数问题的一些研究

前言

使用数组名作为函数参数,或者使用数组名的地址作为函数参数,常常出现于对于字符串的读入问题之中。

常有以下两种写法:

  1. 这是使用数组名作为函数参数
#include<cstdio>
char s[100];
int main() {scanf("%s",s);
}

在编译时不会出现报错和警告。

2.这是使用数组名的地址作为函数参数

#include<cstdio>
char s[100];
int main() {scanf("%s",&s);
}

在编译的时候不会报错,默认不会有警告。但是编译选项中开启-Wall(显示全部警告)就会出现警告。

在这里插入图片描述

警告的原因是,scanf函数的%s选项期望获得一个字符类型的地址,作为读入字符串的起始地址。而&s事实上是一个字符数组类型的地址,而不是字符类型地址。

-Wall编译选项会检查scanf对应的不定参数列表中提供的类型是否正确,因此会警告。不开启-Wall选项则不会检查是否正确,则不会警告。

区别

然而这样的写法虽然会引起编译的警告,但并不会导致编译错误,而且也不会引发程序运行的错误。

准确来说,在大部分实现上,二者达到的目的是一样的。
尽管在标准中,并不确保scanf提供参数类型错误时,也会得到正确的结果,但是由于实现的关系,往往能得到正确的结果。

但是这两种方法仍然是有微小的区别的,在我们将s[0]作为读入的第一个字符的时候,两者没有区别,但假如我们将s[1]作为读入的第一个字符,那它们将会出现不同的结果。

s[0]作为第一个字符

第一种写法

#include<cstdio>
char s[100];
int main() {scanf("%s",s);printf("%s",s);
}

运行结果正确:

在这里插入图片描述

第二种写法

#include<cstdio>
char s[100];
int main() {scanf("%s",&s);printf("%s",s);
}

运行结果正确:

在这里插入图片描述

以s[1]作为第一个字符

第一种写法

#include<cstdio>
char s[100];
int main() {scanf("%s",s+1);printf("%s",s+1);
}

运行结果正确:

在这里插入图片描述

第二种写法

#include<cstdio>
char s[100];
int main() {scanf("%s",&s+1);printf("%s",s+1);
}

运行结果错误:
在这里插入图片描述

这是实际上是发生了访问越界,可以放大一下访问倍数,就会报运行错误:

#include<cstdio>
char s[2000];
int main() {scanf("%s",&s+20);printf("%s",s+20);
}

运行错误:
在这里插入图片描述

具体区别

对于这个字符数组:

char s[10]{};

首先我们知道,s和&s在数值上确实是相等的,但是其指向的类型并不相同。
但是我们知道s+1与&s+1在数值上不一定是相等的:
可以用这个程序对比一下:

#include<iostream>
using namespace std;
int main() {char s[10]{};auto p=&s;cout<<p<<endl;cout<<p+1<<endl;cout<<endl;cout<<static_cast<void*>(s)<<endl;cout<<static_cast<void*>(s+1)<<endl;这里要用关键字static_cast将s的类型从char*转化为void*,是因为cout默认会将char*按照字符串格式输出,而不会选择输出一个地址这里不使用c风格强制类型转换主要是出于习惯
}

我们发现,s+1与s相差了1,而&s+1与&s却相差了10:

在这里插入图片描述

原因

要弄清楚这个问题的原因,就需要先了解清楚s和&s有什么区别。也就是数组名和数组名的地址有什么区别。

那么首先我们要知道,将普通变量+1后,其数值会增加1。但是将指针变量+1后,增加的值等于其指向的类型占用的字节数。
如果我们认为int是4个字节,那么也就是说:

int a[]={0,1};
int* p=a[0];
p++; 此时p数值增加了4,指向了a[1]的位置
此时 *p=1

同理,如果是char类型指针,那么+1后,其数值只会增加1,因为char类型只占用一个字节。

其次,我们需要知道计算机程序在运行中必须要跟踪的数据的三个信息:

  1. 变量被存储在哪里
  2. 变量的值是多少
  3. 变量的类型是什么

我们知道,数组名在C++中通常被看做是指向数组第一个元素的指针,也就是说,s被看做是一个指向s[0]位置的char类型指针,也就是char*。
(当然这个说法并不准确,事实上,s的类型在程序中被跟踪为一个“长度为10的字符数组”,但是s+1则只被识别为“指向s[1]位置的字符指针”)

使用typeid方法获得的类型信息:

这里的"A"表示“array”,是数组。
“10”表示数组长度。
“P”表示一个指针。
“c”表示“char”。
在这里插入图片描述

我们将s看作是指向数组第一个元素的指针,因此s+1比s增加了一个字节,也就是一个char类型的长度。

我们同样可以打出&s的类型:
在这里插入图片描述
这表明编译器认为&s是一个指向长度为10的字符数组的指针,因此&s+1与&s之间相差了10个字节。
指向数组的指针,这个类型十分复杂,以至于用常规方法很难只用一条语句就把它声明出来。
我想到三个方法可以把它声明出来:

  1. 可以使用decltype方法自动推导类型:
decltype(s) *p=&s;
  1. 可以使用auto方法自动推导类型:
auto p=&s;
  1. 可以使用多条语句来声明此类型
	typedef char T[10]; 先用typedef语句声明一个T类型,T类型是一个长度为10的字符数组T* p=&s; 			再声明一个T类型指针

后记

于是皆大欢喜。

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

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

相关文章

【如何构建自己的基于Arduino的Scara 机器人】

【如何构建自己的基于Arduino的Scara 机器人】 1. 概述2. Scara机器人3D模型3. 3D打印机器人零件4. 组装机器人5. SCARA机器人电路图6. 完成装配7. SCARA机器人的工作原理8. 对 SCARA 机器人进行编程 – Arduino 和处理代码9. 总结在本教程中,我们将学习如何构建基于 Arduino …

导出LLaMA ChatGlm2等LLM模型为onnx

通过onnx模型可以在支持onnx推理的推理引擎上进行推理&#xff0c;从而可以将LLM部署在更加广泛的平台上面。此外还可以具有避免pytorch依赖&#xff0c;获得更好的性能等优势。 这篇博客&#xff08;大模型LLaMa及周边项目&#xff08;二&#xff09; - 知乎&#xff09;进行…

leetcode 399-除法求值

法一&#xff1a;并查集 分析示例1&#xff1a; a / b 2.0 a/ b 2.0 a/b2.0&#xff0c;说明 a 2 b a2b a2b&#xff0c; a a a和 b b b在同一个集合中 b / c 3.0 b/c3.0 b/c3.0&#xff0c;说明 b 3 c b3c b3c&#xff0c; b b b和 c c c在同一个集合中 求 a / c a/…

微服务——ES实现自动补全

效果展示 在搜索框根据拼音首字母进行提示 拼音分词器 和IK中文分词器一样的用法&#xff0c;按照下面的顺序执行。 # 进入容器内部 docker exec -it elasticsearch /bin/bash# 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch…

【C++】红黑树的原理与实现

文章目录 一、引言 二、红黑树的概念与性质 2、1 红黑树的概念 2、2 红黑树的性质 三、红黑树的定义与实现 3、1 红黑树的定义 3、2 插入新节点 3、2、1 默认插入红色节点 3、3 插入情况分类 3、3、1 情况一&#xff08;根据颜色向上调整&#xff09; 3、3、2 情况二&#xff0…

AIGC技术到底是什么?为什么这么火热?

AIGC技术到底是什么&#xff1f;为什么这么火热&#xff1f; ALCG技术到底是什么&#xff1f;AIGC技术的发展史AIGC技术特点AIGC技术主要用途ALGC技术未来发展 ALCG技术到底是什么&#xff1f; AIGC&#xff08;Artificial Intelligence in Game Creation&#xff09;技术是指…

OpenLayers实战,OpenLayers实现气象台风飓风运动轨迹运动动画,可调台风旋转速度和运动速度,静态图片旋转动画

专栏目录: OpenLayers实战进阶专栏目录 前言 本章使用OpenLayers实现气象中常用的台风或者飓风运动轨迹动画,支持调整台风图标旋转速度和运动速度。 不同的台风可以设置不同的运动速度和旋转速度,也可以通过变量控制图片不旋转。 本章图片使用静态png图片,并非gif动态图。…

中间件多版本冲突的4种解决方案和我们的选择

背景 在小小的公司里面&#xff0c;挖呀挖呀挖。最近又挖到坑里去了。一个稳定运行多年的应用&#xff0c;需要在里面支持多个版本的中间件客户端&#xff1b;而多个版本的客户端在一个应用里运行时会有同名类冲突的矛盾。在经过询问chatGPT&#xff0c;百度&#xff0c;googl…

在Python中定义Main函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 许多编程语言都有一个特殊的函数&#xff0c;当操作系统开始运行程序时会自动执行该函数。 这个函数通常被命名为main()&#xff0c;并且依据语言标准具有特定的返回类型和参数。 另一方面&#xff0c;Python解释器从文件…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department&#xff1a; 编写一个 SQL 查询来重新格式化表&#xff0c;使得新的表中有一个部门 id 列和一些对应 每个月 的收入&#xff08;revenue&#xff09;列。 查询结果格式如下面的示例所示&#xff1a; 解题思路 1.题目要求我们重新格式化表&#xff0c;…

Sentieon | 应用教程: 关于读段组的建议

介绍 本文档描述了使用Sentieon Genomics软件时&#xff0c;推荐使用RGID字段以最小化潜在问题的用法。 本文档能帮助您确定设置所使用的bam文件中RG标签的不同字段的最佳实践方法。 RG字段及其用法的详细描述 RG字段的详细描述 SAM格式规范http://samtools.github.io/hts-…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentV…

教雅川学缠论06-中枢

本系列文章之前讲的内容都只有上升和下降两类趋势&#xff0c;并没有提及盘整&#xff0c;在缠论中&#xff0c;中枢这个新词汇用来定义盘整&#xff0c;中枢&#xff1a; 1.至少由5条线段&#xff08;或笔&#xff09;组成 2.中枢是有方向的&#xff0c;中枢左右两侧外面的线&…

【locust】使用locust + boomer实现对接口的压测

目录 背景 环境安装 脚本编写 master slave节点&#xff08;golang/boomer&#xff09; 问题 资料获取方法 背景 很早之前&#xff0c;考虑单机执行能力&#xff0c;使用locust做过公司短信网关的压测工作&#xff0c;后来发现了一个golang版本的locust&#xff0c;性能…

替换开源LDAP,某科技企业用宁盾目录统一身份,为业务敏捷提供支撑

客户介绍 某高科技企业成立于2015年&#xff0c;是一家深耕于大物流领域的人工智能公司&#xff0c;迄今为止已为全球16个国家和地区&#xff0c;120余家客户打造智能化升级体验&#xff0c;场景覆盖海陆空铁、工厂等货运物流领域。 该公司使用开源LDAP面临的挑战 挑战1 开源…

01《Detecting Software Attacks on Embedded IoT Devices》随笔

2023.08.05 今天读的是一篇博士论文 论文传送门&#xff1a;Detecting Software Attacks on Embedded IoT Devices 看了很长时间&#xff0c;发现有一百多页&#xff0c;没看完&#xff0c;没看到怎么实现的。 摘要 联网设备的增加使得嵌入式设备成为各种网络攻击的诱人目标&…

c#设计模式-创建型模式 之 工厂模式

前言&#xff1a; 工厂模式&#xff08;Factory Pattern&#xff09;是一种常用的对象创建型设计模式。该模式的主要思想是提供一个创建对象的接口&#xff08;也可以是抽象类、静态方法等&#xff09;&#xff0c;将实际创建对象的工作推迟到子类中进行。这样一来&#xff0c…

第一百二十四天学习记录:C++提高:STL-deque容器(上)(黑马教学视频)

deque容器 deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别 vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低 deque相对而言&#xff0c;对头部的插入删除速度比vector快 vector访问元素的…

cpu util margin,cpu freq margin

【cpufreq governor】cpu util 和 cpu margin怎么计算的_悟空明镜的博客-CSDN博客 cpu util margin&#xff0c;cpu freq margin 根据policy_util schedtune_margin 作为算力选对应的cpu cluster或调频

dubbo之整合SpringBoot

目录 zookeeper安装 1.拉取ZooKeeper镜像 2.新建文件夹 3.挂载本地文件夹并启动服务 4.查看容器 5.进入容器&#xff08;zookeeper&#xff09; Dubbo Admin安装 1.下载dubbo-admin 2.zip包解压 3.修改配置文件 4.打包项目 5.启动jar 6.访问 构建项目 api模块 1.创建…