发表于2024-9-4 18:30
显示全部楼层
此帖出自stm32/stm8论坛
最新回复
昨天下午一直在研究这个问题现象,今天早早的又来开始破案了,百度了一下在Dev-C++中调用scanf函数为什么会把其他局部变量改掉的问题,没有查找到特别相近的答案,理论上来说scanf函数已经运行这么多年,应该是不会出这种BUG的,当看到有人对scanf函数的取值分析我才注意到取值类型和数据对齐的问题,以下是的我试验分析过程,大家看看对不对:
1、把局部变量a b的存储地址打印出来,可见由于电脑是64位的,所以变量的内存栈地址也是64位的,其中局部变量a地址为0x62FE1F,字节对齐,局部变量b地址为0x62FE1E,为半字对齐,位置上与a相邻。
此时输入B33,打印结果如图,输出的结果确实为"? B",对于为什么显示"?",这里我也做了实验,对于Dev-C++来说以char类型打印0xEF 0xED等可能由于没有支持相应的扩展字符,所以统一显示为"?",而不是代表变量a的值是字符"?"的数值0x3F(63)。所以我的疑问1:中兴的出题人也有想考查这一点?还要做题的人要非常了解各个开发环境能显示的字符范围?而且题目里面也没有指定是在哪个环境运行,那又有多少人知道当打印输出"?"号时,真实的16进制数据是多少?
[attach]840697[/attach]
2、关于执行scanf函数之后,局部变量被修改为0的问题,这是比较神奇的问题,经过分析之后我认为在不同的平台上运行这段代码,得到的结果可能会不一样,我的分析如下:
1)从上面打印的变量地址可以看到,由于a b都是char型变量,所以在内存栈中分配的大小就是1字节,这个是正确的
2)执行getchar()函数后,确定此时变量a=’B'=66,说明取输入值无问题
3)执行scanf()函数后,此时变量a的值竟然变成了0,这是关键的点,最终影响到了后面的结果值。为什么会这样呢?我们可以看到scanf函数的参数是取一个Int型数据,传入的存储地址是变量b的地址,根据取值类型的原则,scanf函数会把从键盘输入的数值33保存到指定的地址,由于数值33是int类型,所以对应的10进制数据是0x00000021,但是变量b的地址是0x62FE1E,所以软件会从此地址开始写入int数据,即内存栈中从低地址到高地址的数据为:21 00 00 00,可见局部变量a对应地址0x62FE1F的数据变成了00,所以才出后面打印原始值时a=0的现象。另外说一点,如果这段代码放在arm单片机中,由于写入int型数据的地址不是字对齐,那就会出现字节不对齐造成的硬件错误,当然在编译器编译时可能已经会解决此问题,但是像第3)点说的,不对齐也能直接写入不报错的也可能是跟系统和编译器有关系吧。
4)为了验证3)中的推测,我现在输入B16706,其中int型数值16709=0x00004145,即低2字节对应的字符为'A'和'E',可见在执行完scanf函数后变量a变成了'A',变量b变成了'E',与存储地址上是相一致的,说明3)中的猜测是正确的,变量a的值会因为scanf的输入的类型参数而被影响。
[attach]840699[/attach] 继续验证,将变量b定义成int型,同样输入"B33",可见结果就变成了我第一次手算的结果1 B,因为把变量b定义成int型后,它是会进行双字对齐(因为是64位系统)的,可见变量b地址为0x62FE18,这样执行scanf函数之后,变量b有独立的存储空间,就不会把变量a的值给覆盖掉了,所以运行结果就会正常。
[attach]840701[/attach]
综上,我花了将近一天进行验证测试,得到这些结论,也算是有收获,至少弄清楚了问题现象出现的原理,以后在编程开发的时候需要注意这些不起眼的陷阱。
另外,我也想探讨一下中兴的面试官出此题的目的是想考查哪几个点的内容呢,我也想知道自己的这些分析是不是出题人心中的答案,如果有知晓和坛友不妨分享一二。
考点1:getchar函数的使用?
考点2:scanf函数的使用?
考点3:char类型变量在不同开发环境下的显示内容?
考点4:scanf函数执行后修改变量a值的原因?
考点5:+、-双目运算符的优先级?
详情
回复
发表于 2024-9-7 10:28
| ||
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
||
| |
|
|
发表于2024-9-5 08:33
显示全部楼层
| |
|
|
此帖出自stm32/stm8论坛
| ||
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
||
此帖出自stm32/stm8论坛
点评 | ||
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
||
| |
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
|
此帖出自stm32/stm8论坛
| ||
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
||
此帖出自stm32/stm8论坛
点评 | ||
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
||
发表于2024-9-5 17:27
显示全部楼层
| |
|
|
发表于2024-9-6 08:20
显示全部楼层
此帖出自stm32/stm8论坛
点评 | ||
|
||
| |
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
|
|
发表于2024-9-6 10:40
显示全部楼层
此帖出自stm32/stm8论坛
| ||
|
||
发表于2024-9-6 18:08
显示全部楼层
此帖出自stm32/stm8论坛
| ||
|
||
发表于2024-9-7 10:28
显示全部楼层
此帖出自stm32/stm8论坛
| ||
|
||
EEWorld Datasheet 技术支持