的printf( "%%% S", "你好")

pho*_*nix 1 c objective-c

如果我写printf("%%%s","hello"),它是如何被编译器解释的?某人,开导我.

小智 13

编译器简单地将此解释为printf使用两个字符串作为参数进行调用(但请参阅Zack的注释).

这发生在编译时(即编译器执行此操作):

字符串("%%%s"和"hello")被直接复制到可执行文件中,编译器按原样保留它们.

这在运行时发生(即C标准库在应用程序运行时执行此操作):

printf代表'打印格式化'.调用此函数时,至少需要一个参数.第一个参数是格式.下一个参数是这种格式的"参数".它们的格式与第一个参数中指定的格式相同.

IMG


关于优化

我编写了一个示例并运行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)

C代码

#include <stdio.h>

int main() {
  printf("%%%s", "hello");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

printftest_unopt.s(未优化)

; ...
_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)

printftest_opt.s(优化)

; ...
_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");.:)

  • @phoenix编译器不会查看您输入的参数.C标准库就是这样做的."Hello"`不包含任何格式说明符(`%s`,`%c`,`%d`等)的事实意味着下一个参数(在这种情况下只是"世界"`)赢了使用. (2认同)

Ern*_*ill 7

"%%"表示打印实际的"%"字符; %s表示从参数列表中打印字符串.所以你会看到"%hello".

  • @phoenix是的你可以,但这并没有给printf任何真正的工作要做,所以最好写成`fputs("%Hello",stdout)`. (5认同)