2.4 输入和显示

news2024/11/26 8:56:37

本节必须掌握的知识点:

示例五源代码

代码分析

汇编解析

2.4.1 示例五

格式化输入函数scanf

scanf函数可以从键盘读取输入的信息。scanf函数同样可以像printf函数那样,通过转换说明“%d”来限制函数只能读取十进制数。scanf函数的参数为可变参数,参数的个数由格式化说明符的个数决定,可以同时接受键盘输入多个值。scanf函数以回车符、制表符或者空格表示输入结束。

示例代码五

/*

显示并确认输入的整数值

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

int num;

printf("请输入一个整数:");

scanf_s("%d", &num);//注意,scanf函数读取变量时,变量名前必须加&

printf("您输入的整数是%d。\n", num);

system("pause");

return 0;

}

●输出结果:

请输入一个整数:12

您输入的整数是12。

提示

1. scanf函数读取变量时,变量名前必须加&地址符,表示接收键盘输入的值存储到该地址处。

2.使用scanf函数,高版本的VS会显示错误提示信息如下:

error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

1>c:\program files (x86)\windows

kits\10\include\10.0.18362.0\ucrt\stdio.h(1275): note: 参见“scanf”的声明

解决方法:

方法1:在程序最前面加宏定义:

#define_CRT_SECURE_NO_DEPRECATE

方法2:在程序最前面加:

#pragma warning(disable:4996)

方法3:把scanf改为scanf_s;推荐使用的方法。

方法4:无需在程序最前面加宏定义,只需在新建项目时取消勾选“SDL检查”即可。

方法5:若项目已建立好,在项目属性里关闭SDL。

方法6:在工程项目设置一下就行:将报错的宏定义放到:“项目属性”>“C/C++” > “预处理器”> “预处理器定义”。

方法7:在“项目属性”>“C/C++ ”>“命令行”中添加:/D _CRT_SECURE_NO_WARNINGS就可以了。

3.scanf_s() 函数并不是C标准库函数,而是VS提供的函数,其功能虽然与scanf() 相同,但却比 scanf() 安全,因为 scanf_s() 是针对“ scanf()在读取字符串时不检查边界,可能会造成内存泄露”这个问题设计的。

scanf_s()用于读取字符串时,必须提供一个数字以表明最多读取多少位字符,以防止溢出。例如,scanf_s("%s", buf, 5);

当scanf_s()读取非字符串时,无需考虑内存溢出问题。例如,scanf_s("%d", &num);

2.4.2 代码分析

int num;

第一步:声明一个int类型的变量num,未初始化。

printf("请输入一个整数:");

第二步:调用输出函数printf打印提示信息,提示用户输入一个整数值,这是非常人性化的设计。

scanf_s("%d", &num);//注意,scanf函数读取变量时,变量名前必须加&

第三步:调用scanf_s函数,接收键盘输入,格式化说明符’%d’表示接收输入一个32位整数值,并且存储到num偏移地址处。&no表示取变量num的地址。

printf("您输入的整数是%d。\n", num);

第四步:再次调用printf函数输出结果。

2.4.3 汇编解析

汇编代码

;FileName:2-4-1.asm

;例5:示例代码4-1显示并确认输入的整数值

;by:bcdaren

;2023.08.27

;==================

;C标准库头文件和导入库

include vcIO.inc

.data ;全局区

num sdword ?;全局变量

.const  ;常量区

szMsg1 db "请输入一个整数:",0     

szMsg2 db "%d",0

szMsg3 db "您输入的整数是%d。",0dh,0ah,0

.code ;代码区

start:

;提示信息

push offset szMsg1 ;格式化常量字符串偏移地址入栈

call printf ;调用printf函数输出结果

;接收键盘输入

lea esi,num ;取变量num地址

push esi

push offset szMsg2

call scanf

;输出结果

invoke printf,offset szMsg3,num

;     

invoke _getch;等待输入单个字符

ret;结束返回

end start

上述汇编代码中引用了C标准库函数scanf,在vcIO.inc头文件中已声明。因为没有使用VS编译器,因此这里不可以使用scanf_s函数。调用scanf函数前,先使用lea指令取变量num的地址,然后入栈,接着将格式化常量字符串szMsg2入栈,最后call指令调用scanf函数,接收键盘输入一个整数值,并存储到no偏移地址处。

反汇编代码

int num;

printf("请输入一个整数:");

00E61952 push offset string

"\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0E67B30h) 

00E61957 call _printf (0E6104Bh) 

00E6195C add esp,4 

scanf_s("%d", &no);//注意,scanf函数读取变量时,变量名前必须加&

00E6195F lea eax,[num] 

00E61962 push eax 

00E61963 push offset string "%d" (0E67B44h) 

00E61968 call _scanf_s (0E61154h) 

00E6196D add esp,8 

printf("您输入的整数是%d。\n", num);

00E61970 mov eax,dword ptr [num] 

00E61973 push eax 

00E61974 push        offset string

"\xc4\xfa\xca\xe4\xc8\xeb\xb5\xc4\xd5\xfb\xca\xfd\xca\xc7%d\xa1\xa3\n" (0E67B48h) 

00E61979 call _printf (0E6104Bh) 

00E6197E add esp,8 

2-4-1.c的反汇编代码中,编译器调用的是scanf_s函数,先用lea指令取变量no地址,然后两个push参数入栈,与汇编代码一样。

此外,反汇编代码中,调用printf函数时的第一个参数格式化常量字符串对应的是中文机内码,可以参阅《X86汇编语言基础教程》第四章常用编码规则讲述的汉字编码规则。

实验十七:验证整数常量值作为指令操作数存储在代码段中

第一步:打开DtDebug调试器。

第二步:将汇编代码生成的2-3-1.exe程序拖入调试器。

第三步:按Ctrl+F9,进入程序的入口地址,即程序代码段的起始位置。

第四步:找到整数常量值的赋值语句,如图2-9所示。

                图2-9 整数常量值

结论

【注意】红色方框内的语句,右边为常量值的赋值语句MOV DWORD PTR DS:[1E3010],2

意思为将整数常量值2存入数据段的偏移地址0x001E3010地址处。我们再看左侧汇编指令对应的硬编码,05C7为MOV DWORD PTR指令机器码,001E3010为数据段内的偏移地址,00000002为整数常量值,作为该条机器指令的一部分存储在代码段中。注意X86 CPU字节为单位的小端存储方式,低地址为低字节数据,高地址为高字节数据。

实验十八:乘法运算

VS新建项目2-4-2.c:

/*

读取一个整数并显示其3倍的值

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

int num;

printf("请输入一个整数:");

scanf_s("%d", &num);//读取整数值

printf("它的3倍的值是%d\n", 3 * num);

system("pause");

return 0;

}

●输出结果:

请输入一个整数:11

它的3倍的值是33

请按任意键继续. . .

练习

1、请读者将2-4-2.c翻译成汇编语言实现。

2、请读者分析2-4-2.c的反汇编代码。

实验十九:输出函数puts

VS新建项目2-4-3.c:

/*

显示读取到的两个整数的和

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

int n1, n2;

//puts函数功能:输出字符串并换行,等同于printf("...\n")

puts("请输入两个整数。");

printf("整数1:");scanf_s("%d", &n1);

printf("整数2:");scanf_s("%d", &n2);

printf("它们的和是%d。\n", n1 + n2);  //显示和

system("pause");

return 0;

}

●输出结果:

请输入两个整数。

整数1:1

整数2:2

它们的和是3。

请按任意键继续. . .

【注意】puts函数只有一个参数,仅用于输出零结尾字符串。

练习

1、请读者将2-4-3.c翻译成汇编语言实现。

2、请读者分析2-4-3.c的反汇编代码。

实验二十:显示读取到的两个整数的和

VS新建项目2-4-4.c:

/*

显示读取到的两个整数的和

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

int n1, n2;

int sum;//和

puts("请输入两个整数:");

printf("整数1:");scanf_s("%d", &n1);

printf("整数2:");scanf_s("%d", &n2);

sum = n1 + n2;

printf("它们的和是%d。\n", sum);//显示和;

system("pause");

return 0;

}

●输出结果:

请输入两个整数:

整数1:1

整数2:2

它们的和是3。

请按任意键继续. . .

【注意】实验十九和实验二十的区别,实验二十定义了一个int类型变量sum,用于保存变量n1+n2的和。当我们需要多次使用变量和的情况下,应该定义一个sum变量保存变量和。如果只打印一次,则不需要定义变量sum,可以根据实际需要,灵活设计。

总结

1.计算机的内存是一个以字节为单位的线性存储空间,每个字节都有一个独立的地址编号。计算机程序通过内存地址读写该地址相应的存储空间。

2.源程序中的变量和常量都是存储在内存中的数据。全局变量存储在全局区,局部变量存储在栈区,字符串常量存储在常量区。整数常量或字符常量作为机器指令的操作数存储在代码区,可以直接引用,无需地址编号。

3.变量名就是用符号表示的地址编号。全局变量是相对于全局区内的偏移地址,局部变量是相对于栈区的偏移地址,常量字符串是相对于常量区的偏移地址。

4.对变量的引用:

在汇编语言中,使用mov指令引用变量时,表示从该变量偏移地址处取该地址存储的值。例如,mov eax,[a](与mov eax,a等价)表示将变量a地址处的值送入eax寄存器。如果取变量的地址,则使用lea指令。例如,lea esi,a表示将变量a的地址送入esi寄存器。

在C语言中,没有办法通过指令来区分取变量地址还是取值,因此变量名表示该地址处存储的值,变量名前添加地址符&表示变量地址,地址前添加*号(解引用运算符)表示取该地址处的值。后面我们将要学习的指针就是地址的意思,从汇编的角度理解指针是一件再简单不过的事情了。

例如:

a = 1;该语句执行后,变量名a表示变量的值为1。而这条语句的真实含义是指将整数常量值1存储到变量a偏移地址处,即&a地址处。

*(&a) = 1;这条语句的含义是将整数常量值1送入变量a地址处,等价于语句a = 1;这里的*号表示解引用,即表示变量a地址处的值等于1。

5.常量字符串:

在汇编代码中,常量字符串需要使用一个符号表示常量字符串在常量区内的偏移地址。例如示例五汇编代码中的szMsg1,使用操作符offset取szMsg1的偏移地址:offset szMsg1。

取出常量字符串的偏移地址就可以对字符串进行读操作了。

如果字符串存储到全局区或者栈区,那么该字符串就变成了变量了,一个以ASCII字符组成的数组,不仅可以对字符串进行读操作,还可以对字符串进行写操作。我们将在第十一章字符和字符串章节中详细讲解。

在C语言中,常量字符串存储在常量区,采用直接引用的方式对常量字符串进行操作。例如puts("请输入两个整数:");puts函数的唯一参数是一个常量字符串,可以直接对其引用。但是记住,对常量字符串的引用其实是直接引用该常量字符串的在常量区内的偏移地址。

何以证明?请看puts语句对应的反汇编语句:

push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xc1\xbd\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0F27B30h)

offset string就表示该常量字符串的偏移地址(0F27B30h)。

6.const是C语言编译器的修饰词,用于修饰变量。例如const int j;表示在变量j的存续期间,不可以修改变量j的值,把变量j当作是常量看待,其实并没有改变变量j的真实属性,即变量j并不会因此而变成一个常量,不会改变变量j的存储区。编译器在编译源程序时会检查const修饰过的变量的值是否被修改,如果被修改,则会提示错误信息error C2166: 左值指定 const 对象。const修饰词的作用是帮助程序员避免不必要的错误。程序员在无意中修改了本来不该被修改的变量的值,特别是对全局变量的无意修改。而在汇编语言中并没有类似const这样的修饰词,因此汇编语言对程序员的要求更高。

练习

1、 编写一段程序,从键盘读取两个整数,计算并显示两个整数的乘积。

2、 编写一段程序,从键盘读取三个整数,计算并显示三个整数的和。

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

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

相关文章

雷军-2022.8小米创业思考-6-互联网七字诀之快:天下武功,唯快不破;快不是目的,快是手段;不要用战术上的勤奋掩盖战略上的懒惰。

第六章 互联网七字诀 专注、极致、口碑、快&#xff0c;这就是我总结的互联网七字诀&#xff0c;也是我对互联网思维的高度概括。 快 我们期待非常多的快&#xff0c;比如研发进展快、库存周转快、资金回笼快等等。但在这里&#xff0c;我们集中讨论的是公司在业务发展和面对…

【5分钟学会一个知识点】01.Elasticsearch基本操作-增删改查

目录 【5分钟学会一个知识点-探索现代搜索与分析引擎的魅力】01.Elasticsearch基本操作-增删改查1.基本操作1.1索引操作1.2文档操作1.3查询1.4修改数据1.5查询1.5.1条件查询1.5.1.1遍历所有的索引1.5.1.2查询某个索引1.5.1.3条件查询1&#xff1a;使用GET url传参数1.5.1.4条件…

18、案例实战:上亿请求轻松应对,看年轻代垃圾回收如何助力电商性能飞跃!

18.1、背景引入 我们通常会通过案例分析&#xff0c;来指导大家如何在不同的场景下&#xff0c;预测系统的内存使用模型。我们需要合理地调整新生代、老年代、Eden和Survivor各个区域的内存大小&#xff0c;然后尽可能地优化参数&#xff0c;以减少新生代对象进入老年代的情况…

An 2024下载

An2024下载&#xff1a; 百度网盘下载https://pan.baidu.com/s/1cQQCFL16OUY1G6uQWgDbSg?pwdSIMS Adobe Animate 2024&#xff0c;作为Flash技术的进化顶点&#xff0c;是Adobe匠心打造的动画与交互内容创作的旗舰软件。这款工具赋予设计师与开发者前所未有的创意自由&#x…

火绒安全原理、用法、案例和注意事项

火绒安全是一款功能强大的安全软件&#xff0c;它采用了先进的安全技术和算法&#xff0c;通过实时监测、恶意代码识别、防火墙功能、沙箱技术和网络保护等多种手段&#xff0c;为用户提供全面的计算机安全防护。 1.为什么选用火绒安全&#xff1f; 火绒安全是一款优秀的安全软…

用lobehub打造一个永久免费的AI个人助理

Lobe Chat是一个开源的高性能聊天机器人框架&#xff0c;它被设计来帮助用户轻松创建和部署自己的聊天机器人。这个框架支持多种智能功能&#xff0c;比如语音合成&#xff08;就是让机器人能说话&#xff09;&#xff0c;还能理解和处理多种类型的信息&#xff0c;不仅限于文字…

AI图书推荐:用GPT-4进行预测分析的实用指南

《用GPT-4进行预测分析的实用指南》&#xff08;A Practical Guide to Predictive Analytics with GPT-4&#xff09;为读者提供了一个全面的指南&#xff0c;介绍了如何利用GPT-4的强大预测能力&#xff0c;从理解预测分析的基础&#xff0c;到掌握GPT-4的使用&#xff0c;再到…

基于yolov5+gradio目标检测演示系统设计

YOLOv5与Gradio&#xff1a;目标检测可视化展示的新篇章 随着人工智能技术的深入发展&#xff0c;目标检测已成为现代智能应用中的一项关键技术。YOLOv5&#xff0c;作为目标检测领域的杰出代表&#xff0c;凭借其出色的实时性和准确性&#xff0c;赢得了广泛的认可和应用。而…

电力场景设备漏油检测数据集VOC+YOLO格式338张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;338 标注数量(xml文件个数)&#xff1a;338 标注数量(txt文件个数)&#xff1a;338 标注类别…

数据缓存,可以尝试RocksDB了

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen shigen在最近的学习中&#xff0c;接触到了一款新的缓存数据库RocksDB&#xff…

SQL语句优化技巧

目录 1、sql语句规范 2、sql语句优化 1、sql语句规范 MySQL在Linux系统下数据库名&#xff0c;表名&#xff0c;存储过程名&#xff0c;函数名称&#xff0c;触发器名称等区分大小写&#xff0c;列名不区分大小写&#xff0c;原因是这些操作系统下文件名称区分大小写。 MySQL…

LNMP 环境下 Nginx 1.26.0 开启 HTTP/3 QUIC 支持

前几天 Nginx 1.26.0 主线版发布了&#xff0c;明月总算抽出时间更新了&#xff0c;那么自然的也要尝试一下开启 HTTP/3 QUIC 支持了&#xff0c;今天就给大家分享一下。对于我们的网站来说开启 HTTP/3 QUIC 最大的好处是页面载入速度的提升&#xff0c;尤其是在支持 HTTP/3 QU…

安卓模拟器怎么修改ip地址

最近很多老铁玩游戏的&#xff0c;想多开模拟器一个窗口一个IP&#xff0c;若模拟器窗口开多了&#xff0c;IP一样会受到限制&#xff0c;那么怎么更换自己电脑手机模拟器IP地址呢&#xff0c;今天就教大家一个修改模拟器IP地址的方法&#xff01;废话不多说&#xff0c;直接上…

牛客NC363 开锁【中等 BFS Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/e7cbabbf7e0a41ec98055ee5f3d33bbe https://www.lintcode.com/problem/796 思路 Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#x…

文件系统(未打开的文件)

之前我们讲述的一些文件操作都是在文件被打开的基础上的&#xff0c;因为用户想要对某个文件做操作的话&#xff0c;这个文件一定是被打开的&#xff0c;也就是一定是内存级的文件。 但是有的没有被操作的文件&#xff0c;是在磁盘中的&#xff0c;我们的笔记本是在SSD中&…

Debian Linux 下给Nginx 1.26.0 编译增加Brotli算法支持

明月发现参考【给Nginx添加谷歌Brotli压缩算法支持】一文给出的方法&#xff0c;在Debian Linux 12.5下就一直编译失败&#xff0c;主要的错误是因为文件缺失&#xff0c;在专门又安装了apt-get install libbrotli-dev的依赖库后依然会因为文件缺失无法编译完成&#xff0c;就这…

JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测

JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测 目录 JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预…

Postman基础功能-常见类型的接口请求

天空灰暗到一定程度&#xff0c;星辰就会熠熠生辉。大家好&#xff0c;之前给大家分享了关于 Postman 工具的介绍以及安装&#xff0c;在当今数字化的时代&#xff0c;接口请求在软件开发和系统集成中扮演着至关重要的角色。而 Postman 作为一款强大且广受认可的接口测试工具&a…

信息系统项目管理师0105:项目评估与决策(7项目立项管理—7.3项目评估与决策)

点击查看专栏目录 文章目录 7.3项目评估与决策1.评估依据2.评估的程序3.项目评估的内容4.项目评估报告内容大纲记忆要点总结7.3项目评估与决策 项目评估指在项目可行性研究的基础上,由第三方(国家、银行或有关机构)根据国家颁布的政策、法规、方法、参数和条例等,从国民经济…

Java | Leetcode Java题解之第77题组合

题目&#xff1a; 题解&#xff1a; class Solution {List<Integer> temp new ArrayList<Integer>();List<List<Integer>> ans new ArrayList<List<Integer>>();public List<List<Integer>> combine(int n, int k) {List&l…