小智 13
编译器简单地将此解释为printf使用两个字符串作为参数进行调用(但请参阅Zack的注释).
字符串("%%%s"和"hello")被直接复制到可执行文件中,编译器按原样保留它们.
printf代表'打印格式化'.调用此函数时,至少需要一个参数.第一个参数是格式.下一个参数是这种格式的"参数".它们的格式与第一个参数中指定的格式相同.
![]()
我编写了一个示例并运行Clang/LLVM -S:
$ emacs printftest.c
$ clang printftest.c -S -o printftest_unopt.s # not optimized
$ clang printftest.c -S -O -o printftest_opt.s # optimized: -O flag
Run Code Online (Sandbox Code Playgroud)
#include <stdio.h>
int main() {
printf("%%%s", "hello");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
; ...
_main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl $0, %eax
movl $0, -4(%rbp)
movl %eax, -8(%rbp)
xorb %al, %al
leaq L_.str(%rip), %rdi
leaq L_.str1(%rip), %rsi
callq _printf ; printf called here <----------------
movl %eax, -12(%rbp)
movl -8(%rbp), %eax
addq $16, %rsp
popq %rbp
ret
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "%%%s"
L_.str1:
.asciz "hello"
; ...
Run Code Online (Sandbox Code Playgroud)
; ...
_main:
pushq %rbp
movq %rsp, %rbp
leaq L_.str(%rip), %rdi
leaq L_.str1(%rip), %rsi
xorb %al, %al
callq _printf ; printf called here <----------------
xorl %eax, %eax
popq %rbp
ret
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "%%%s"
L_.str1:
.asciz "hello"
; ...
Run Code Online (Sandbox Code Playgroud)
正如你所看到的(在__TEXT,__cstring,cstring_literals部分和中callq到printf),LLVM(一个非常,非常好的编译器)也没有优化printf("%%%s", "hello");.:)
"%%"表示打印实际的"%"字符; %s表示从参数列表中打印字符串.所以你会看到"%hello".