print_once,它是如何阻塞的?

我试图理解实现一次打印function,这段代码工作正常; 但是我无法理解一些事情:1)这是如何阻塞的? 也许我无法正确清除它,但只是想知道, C的哪些属性会让这种情况发生?

1 #include  2 3 #define _TRACE_ 4 5 #ifdef _TRACE_ 6 #define print_once(fmt, ...) \ 7 ({ \ 8 static bool __print_once=false; \ 9 if(!__print_once) { \ 10 __print_once = true; \ 11 do { \ 12 printf(fmt, ##__VA_ARGS__); \ 13 }while(0); \ 14 } \ 15 }) 16 #else 17 #define print_once(fmt, ...) \ 18 printf("\n"); 19 #endif 20 21 void func() 22 { 23 print_once("func\n"); 24 } 25 int main(int argc, char* argv[]) 26 { 27 print_once("test1\n"); 28 //:w 29 print_once("test22\n"); 30 for(int i =0; i < 2; i++) 31 print_once("loop\n"); 32 func(); 33 func(); 34 return 0; 35 } 

这不是标准的C,它使用一个名为语句表达式的GCC扩展(有趣的({...})语法)。 (它也不是线程安全的。)

它的工作原理是在每个print_once调用站点添加一个静态布尔值(每个调用站点都有自己的静态标志),最初为false ,在第一次运行该段代码时设置为true(代码仅在确实为false打印) )。 因此,后续执行同一代码块将不会打印任何内容。

请注意,不需要使用GCC扩展,并且宏的构造很奇怪 – 它可能从更简单的东西扩展而来。 这应该是C99兼容的( 可变参数宏需要C99或更高版本),并且在正确的位置有do {...} while(0) “trick”:

 #define print_once(fmt, ...) \ do { static bool flag = false; \ if (!flag) { \ flag = true; \ printf(fmt, ##__VA_ARGS__); \ } \ } while (0)