c语言 window中的<stdio.h>中scanf()函数的隐患

前言:

那是在我一个日常写代码的过程中,我先写了如下的代码:

char string[16] = { 0 };
int* strlen = (int*)malloc(sizeof(int));
*strlen = 0;

然后在我使用scanf()函数并打算输出结果时

scanf("%s",string);
while(string[(*strlen)])
    (*strlen)++;
printf("输入的字符串长度为%d",*strlen);
free(strlen);

突然一个奇怪的数字出现了。

思考:

我是输入较短的字符串时问题就没有出现,但当输入字符串过长就出现bug了。很明显就是过长导致的问题,不过我在输入二十多个字节的字符串是,却是正常显示了。

查看内存和反汇编:

比如我输入二十一个'd'(在二进制的ascii码为100,也就是0x64)(并且地址为该次string字符串的首地址)

可以看到,而且scanf函数接收字符串时,是完全接收了字符串然后再接收完成之后加个0('\0'),但分配给字符串string的大小有30字节(不知道为什么不是16,不过这也在某种程度上提高了scanf的容错率)。

可能的危险:

这种一股脑全吸收字符串的行为十分危险,因为它可能会覆盖掉该栈空间(甚至超出)以下的数据,甚至在使用堆的时候不仅会把记录堆数据的地址的指针覆盖掉,还会因为覆盖掉地址的堆数据泄露。而我在前言的时候使用堆的分配也正是展现了这一风险

最后:

这种scanf函数的隐患想必一定是有人指出来了(不然也不会有scanf_s()函数的存在),不过我在这记录下来。一来是为了提醒为了可能犯错的我,二来也是希望更多人知道scanf函数的隐患(在我上c语言课的时候老师一次也没有提到这种隐患)。

PS:

这里我举例我的环境所在(Windows 11,Microsoft Visual Studio)的标准库scanf函数,因为不同操作系统的标准库实现可能是不同的,所以在别的操作系统中的scanf就很安全。这也就是我为什么标题会写“window中的<stdio.h>中scanf()函数的隐患”

以下是一个简单的C语言按键声光报警系统的代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <windows.h> int main() { int key; printf("Enter the key (0-9): "); scanf("%d", &key); if(key >= 0 && key <= 9) { printf("Key pressed: %d\n", key); printf("Alarm activated!\n"); Beep(1000, 2000); // 1000 Hz tone for 2 seconds } else { printf("Invalid key entered!\n"); } return 0; } ``` 这个程序会要求用户输入一个数字键(0-9),如果输入的键在这个范围内,程序将打印出“Key pressed: [输入的键]”,然后发出连续2秒的1000 Hz蜂鸣声。如果输入的键不在这个范围内,程序将打印出“Invalid key entered!”。请注意,Beep函数只在Windows操作系统上可用。如果你在其他操作系统上运行这个程序,需要使用其他方法来产生声音。 如果你想要加入闪光灯报警功能,可以使用Windows API的FlashWindowEx函数来实现。具体方法可参考以下代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <windows.h> int main() { int key; printf("Enter the key (0-9): "); scanf("%d", &key); if(key >= 0 && key <= 9) { printf("Key pressed: %d\n", key); printf("Alarm activated!\n"); Beep(1000, 2000); // 1000 Hz tone for 2 seconds // flash the window FLASHWINFO fi; fi.cbSize = sizeof(FLASHWINFO); fi.hwnd = GetConsoleWindow(); fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; fi.uCount = 5; fi.dwTimeout = 0; FlashWindowEx(&fi); } else { printf("Invalid key entered!\n"); } return 0; } ``` 这个程序在蜂鸣声之后,将使用FlashWindowEx函数闪烁控制台窗口5次,以提醒用户注意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值