为何scanf("%s", val);返回NULL?单字符读取及malloc相关问题
问题分析与解决
原代码的核心问题
- 野指针导致未定义行为:
char *val;仅声明了指针,未指向任何有效内存。调用scanf("%s", val)时,会往随机内存地址写入数据,必然引发程序异常(比如返回NULL、崩溃)。 - malloc使用未限制读取长度:
%s格式符默认会持续读取输入,直到遇到空白字符(空格、回车、制表符),这就是输入单个字符后程序仍等待的原因。
正确实现方式
方式一:栈上数组实现(简单高效)
只需存储单个字符+字符串终止符\0,直接定义长度为2的数组即可:
#include <stdio.h> int main(int argc, char *argv[]) { char val[2]; // 1字节存字符,1字节存终止符 if (argc == 2) { // 确保取到的是单个字符并补全终止符 val[0] = argv[1][0]; val[1] = '\0'; } else { // %1s 限制仅读取1个非空白字符,自动添加终止符 scanf("%1s", val); } printf("Val = %s", val); return 0; }
方式二:动态内存分配(malloc)
若必须用char*动态分配,需至少申请2字节空间,同时限制scanf读取长度:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *val = malloc(2); // 分配2字节:字符位+终止符位 if (!val) { // 检查内存分配是否成功 printf("内存分配失败\n"); return 1; } if (argc == 2) { val[0] = argv[1][0]; val[1] = '\0'; } else { scanf("%1s", val); // 强制只读1个字符 } printf("Val = %s", val); free(val); // 释放动态分配的内存 return 0; }
额外说明
如果需要读取任意单个字符(包括空格、回车这类空白字符),可替换scanf为getchar():
// 替换else分支的scanf代码 val[0] = getchar(); val[1] = '\0';
内容的提问来源于stack exchange,提问作者Reece Cristea
相关产品推荐
相关产品推荐

