出于某种原因,加入\n到printf()改变的下面的代码的行为.没有\n打印(null)的代码而\n导致的代码Segmentation fault.
Printf.c
#include <stdio.h>
int main(int argc, char* argv[]){
printf("%s", argv[1]);
}
Run Code Online (Sandbox Code Playgroud)
Printf.c - 输出
$ gcc -o Printf Printf.c
$ ./Printf
(null)
Run Code Online (Sandbox Code Playgroud)
Printf_Newline.c
#include <stdio.h>
int main(int argc, char* argv[]){
printf("%s\n", argv[1]);
}
Run Code Online (Sandbox Code Playgroud)
Printf_Newline.c - 输出
$ gcc -o Printf_Newline Printf_Newline.c
$ ./Printf_Newline
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)
我很想知道这背后的原因.
小智 55
两者都是未定义的行为,所以答案可能会在这里停止.
但至少有一个解释输出(null).这是glibc(GNU C库)的扩展.通过0对%s在printf()被认为是不确定的 C标准,因此很可能导致崩溃.开发人员glibc决定做一些有意义的事情.
然而,第二次崩溃的原因是,使用换行符,编译器决定优化:而不是printf("%s\n", argv[1]),它执行puts(argv[1]),根据C标准在语义上是等效的,因此是允许的优化.但glibcs"(null)-trick"仅在printf().中实现.
程序中还有另一个未定义的行为:您可能访问argv 越界.有没有保证什么价值,你会发现在argv[i]的时候i > argc.有一点点机会argc可能是0,所以你也可以体验其他任何东西.
chq*_*lie 11
如果程序没有给出任何命令行参数,代码在两种情况下都有未定义的行为,因此任何事情都可能发生.
既然你很好奇(对你有好处!),这里有一个你观察到的可能的解释:
printf("%s\n", argv[1]);可以由编译器优化成puts(argv[1]);,而printf("%s", argv[1]);仍然调用printf().
printf接受空指针作为%s转换参数的一些实现,因此输出(null).
puts() 具有未指定的空指针行为,在您的情况下是分段错误.
尝试编译两个没有任何优化(-O0),看看你是否得到(null)输出\n.
您可以使用godbolt的编译器资源管理器,看看如何clang使用-O0更改行为,但不能gcc.