看网上很多讲一些C/C++的问题回答或者文章,经常会遇到UB、UB、UB、UB……
UB就是undefined behavior。也就是语言的官方标准未定义的地方,在不同系统,编译器上行为可能不一致。没错,我们当然不能把UB的效果,当成语言标准。但我们也不能因为某些语法是UB就拒绝学习和探究,毕竟我们学习编程语言都不是抱着《XX语言官方标准》的手册来学的。另外呢,我们工作之中通常也是在特定的系统和编译器上开发的。
今天要讲的内容就是UB的。言归正传。
C语言printf输出NULL
看下这个:
#include <stdio.h>
int main()
{
char* a = NULL;
printf("%s", a);
return 0;
}
printf用%s输出NULL,会有什么行为,大家可能会说,运行会core啊,不能这样写。没错,去空地址寻址,会core掉,好的编码规范,也要求我们在调用函数之前对变量a判非NULL,不过今天我们不谈编码规范。
这段代码在gcc(Linux上测试)和clang(Mac上测试)上其实都不会core掉。而是会正常输出,当然这是UB的:
(null)
再看这个:
printf("%s\n", a);
能正常运行吗?这就有差异了。
gcc运行会段错误。但是clang依旧能正常输出(null)和换行。clang鲁棒性很好,暂且不提了。gcc为什么会因为多了\n就有此差异呢?这是因为gcc对printf有优化。当printf的格式化字符串为"%s\n"的时候,实际 printf("%s\n", a); 会被替换成 puts(a); 而puts 是未针对NULL特殊处理输出成(null),而是直接去寻址导致段错误。
相关阅读:

本文探讨了C/C++编程中遇到的未定义行为(UB)问题,特别是使用printf和C++ IO流输出NULL时的差异。在不同编译器和系统上,这种行为可能导致不可预测的结果,例如在某些情况下不会引发段错误,而在其他情况下则会导致程序崩溃。文章通过实例分析了gcc和clang的行为,并提醒开发者注意潜在的风险和遵循良好的编码规范。
最低0.47元/天 解锁文章
2824

被折叠的 条评论
为什么被折叠?



