1.背景
从表面上而言,看到scanf()数都会觉得这个函数很简单,就是按照给定的格式获取输入数据。但是在实际使用时才发现这个函数还是有一些坑值得注意的。下面分别对使用scanf()的正确情况和错误情况进行记录,以备后用。
2.使用scanf()的正确情况
2.1.示例代码:
2.2.输入、输出结果:
3.使用scanf()的错误情况
3.1.示例代码:
3.2.输入、输出结果:
4.错误现象
错误提示表明变量a附近的栈空间被损坏了。
4.错误原因
正确示例与错误示例的唯一区别就是,在错误示例中变量a的类型由int变为了char。而两种情况下,都是期望使用scanf()按照十六进制的格式输入变量a和b。
首先看一下错误情况下,在scanf()打断点后的程序栈空间:
可以看到,这时char类型的变量a只占用了栈空间0x00C0FD07处的一个字节。int型的变量b占用了4个字节。
接着再看看使用scanf()进行十六进制输入后的程序栈空间,期望是向变量a输入0x30,变量b输入0x40。
然而,可以非常明显地看到,变量a接着的3个字节的栈空间变为了0x00,而非开始的0xCC。所以问题也就出在这里,当scanf()尝试按照十六进制输入故意而char型变量时,会将栈空间中连续的四个字节视为一个整型数。从而导致了栈空间的损坏。
还有一种情况,就是如果两个变量的栈空间相隔很近的条件下,可能会出现一个变量被另一个变量覆盖的情况。例如,如果char型变量a=0x10和int型变量b=0x20在栈空间中是连续入栈的,假设当前栈空间的分布为:0x10 0x20 0x00 0x00 0x00,这时如果使用scanf()按照十六进制再次输入变量a(假设输入的值为0x40),那么当scanf()执行之后,栈空间的内容将会变为:0x40 0x00 0x00 0x00 0x00,最终将导致变量b的值由0x20变为了0x00,这将导致程序的执行出现意料之外的结果。