在使用printf-buffering时避免解析格式字符串

时间:2013-02-17 06:21:46

标签: c printf

在C程序中,我使用了printf("%c", WORD_SEP);这一行,我认为这是不言自明的。

据我所知,printf将解析Format-String“%c”并将其替换为运行时字符WORD_SEP 。这当然是完全可以避免的,因为WORD_SEP是一个编译器#define,因此永远不会改变。

我可以硬编码printf("*");这会更快,但我当然希望保持#define的可维护性 - 它仍然不是最佳的,因为printf仍然需要解析字符串。

有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

非格式化单字符打印:

putc()putchar()fputc()

非格式化字符串打印:

fputs(),以及我的(不是那么)最喜欢的puts()

在旁注中,请避免使用"*"而不是'*',因为"*"在内存中创建了一个带有两个字节的空间,一个用于*,另一个用于\0 '*'。无论您想要哪个单个字符,请使用"*"代替{{1}}

答案 1 :(得分:0)

希望我不会误解这个问题,但如果你想最终做一些像

这样的事情
printf("abc %c xyz", WORD_SEP);

如果没有在运行时插入这个常量字分隔符,你可以先做

#define WORD_SEP "*"

然后再做

printf("abc " WORD_SEP " xyz");

将导致在编译时创建格式字符串。正如下面的评论中所提到的,在这种情况下,您需要注意%中的WORD_SEP字符,因为它现在是格式字符串的一部分。

答案 2 :(得分:0)

  

据我所知,printf将解析Format-String“%c”并在运行时将其替换为字符WORD_SEP。这当然是完全可以避免的,因为WORD_SEP是一个编译器#define,因此永远不会改变。

gcc会优化printf("%c", WORD_SEP);来调用putchar('*')

#include <cstdio>

#define WORD_SEP '*'

int main() {
    printf("%c", WORD_SEP);
}

输出asm:

g++ -S --verbose-asm -o - -DNDEBUG -g -Wall -Wextra -march=native -O3 test.cc | c++filt > test.s

test.s:

main:
    subq    $8, %rsp    
    movl    $42, %edi   
    call    putchar 
    xorl    %eax, %eax  
    addq    $8, %rsp
    ret

gcc也将printf("..." /* no arguments */)优化为puts(),以避免解析没有格式说明符的格式字符串。