C语言传递字符串指针到函数后打印附带内存地址的问题排查
问题根因
这个问题和栈内存机制、指针损坏没有任何关系,属于标准输出缓冲导致的输出拼接错觉:你看到的字符串末尾的144根本不是内存里的脏数据或者地址值,而是后续代码打印的sum变量计算结果。
具体执行逻辑如下:
- 你在main中定义的
char* n = "function pointers"完全合法,字符串字面量自带\0结束符,将其作为实参传递给topic函数的过程中,指针值没有被破坏,指向的内存内容始终正确。 - 问题出在
topic函数内的打印语句:
这行代码的格式字符串末尾没有添加换行符printf("Hello, %s, today's topic id is %s",p,arg);\n。C语言的标准输出stdout默认是行缓冲模式:缓冲区中存储的打印内容,只有遇到换行符、缓冲区写满、主动调用fflush(stdout)、程序正常退出时,才会真正显示到终端上。这行语句执行完后,所有待打印的内容都留在输出缓冲区中,没有立刻显示。 topic函数执行完返回main后,代码继续运行:通过函数指针调用F(97,47),计算得到sum = 97 + 47 = 144,紧接着执行printf("%i",sum);,这行要打印的144会直接追加到现有输出缓冲区的尾部,正好接在之前缓冲区存储的function pointers内容后面。- 等main函数执行完毕、程序准备退出时,C运行时会自动刷新所有输出缓冲区,此时拼接后的整段内容才会一次性显示到屏幕上,让你误以为是打印
arg指针指向的字符串时带出了额外内容。
修复方式
只需要给topic函数内的printf格式串末尾加上换行符,让缓冲区内容在该语句执行完就立刻刷新即可:
printf("Hello, %s, today's topic id is %s\n",p,arg);
修改后你会看到两段输出正常分行显示,不会再出现字符串末尾拼接144的现象。
其他潜在问题提醒
- 代码中
scanf("%s",p)存在堆缓冲区溢出风险:你给p只申请了20字节的堆内存,%s格式符默认会一直读取输入直到遇到空白符,如果用户输入超过19个字符就会越界写入堆内存,触发未定义行为,建议改成scanf("%19s",p)限制最大读取长度。 isalnum类字符检测函数要求传入参数必须是能转换为unsigned char的值或者EOF,如果当前编译环境下char为有符号类型,遇到值为负的字符时会触发未定义行为,循环判断逻辑建议修改为while (isalnum((unsigned char)*p) == 0);,原代码里的双重取反!!属于无意义的冗余写法。- C标准明确规定
sizeof(char)的值固定为1,malloc(20*sizeof(char))可以直接简写为malloc(20),不影响功能但写法更简洁。
内容的提问来源于stack exchange,提问作者Eric 222
相关产品推荐
相关产品推荐

