- 论坛徽章:
- 0
|
前面有版友提出printf族的函数是non reentrant的,所以在信号处理函数中使用是不安全的,俺也参与了讨论
http://linux.chinaunix.net/bbs/viewthread.php?tid=1142533&extra=
但是没有搞清楚具体是为什么
前两天正好看到一段文字,提到printf可以调用一些call back函数
OMG
这实在太令人吃惊了
如果printf可以调用call back函数,这些函数如果访问static/global变量都是可能的,那么printf作为non reentrant就没有疑问了
现在问题变成了探讨printf如何使用call back函数,这是本文的主要目的
查看了一些文档,原来是这么回事
GNU C库中的printf允许自定义格式化字符串,如何处理这些自定义的格式化字符串就是通过用户提供call back函数进行的
什么是自定义格式化字符串呢?
我们知道printf("%i", i)会把i作为integer打印出来,这个%i就是一个格式化字符串,这是printf提供给我们的格式化串
那我们为什么要自定义呢,举个例子
假如现在有这么一个结构
- typedef struct
- {
- char *name;
- }
- Widget;
- Widget mywidget;
- mywidget.name = "mywidget";
复制代码
想打印这个结构体的地址以及名字的话,当然可以这样写
printf("%p\t%s\n", &mywidget, mywidget.name);
但是如果有很多这样的语句,我们就会希望有一种更方便的形式了
比如直接来个
printf ("%W\n", &mywidget);
就能够打印所有需要的内容
这就可以通过自定义一个新的%W格式化串来实现
下面是一个完整的例子,摘自
http://www.gnu.org/software/hell ... f-Extension-Example
有兴趣的编译运行一下就知道这个自定义格式化串的用法了
更多信息见
http://www.gnu.org/software/hell ... omizing-Printf.html
/*我想用C代码模式来着,但是不知道是服务器还是我的浏览器的原因,总是打不开代码模式的窗口,老是弹出http://www.chinaunix.net/hot.shtml*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <printf.h>
-
- typedef struct
- {
- char *name;
- }
- Widget;
-
- int
- print_widget (FILE *stream,
- const struct printf_info *info,
- const void *const *args)
- {
- const Widget *w;
- char *buffer;
- int len;
-
- /* Format the output into a string. */
- w = *((const Widget **) (args[0]));
- len = asprintf (&buffer, "<Widget %p: %s>", w, w->name);
- if (len == -1)
- return -1;
-
- /* Pad to the minimum field width and print to the stream. */
- len = fprintf (stream, "%*s",
- (info->left ? -info->width : info->width),
- buffer);
-
- /* Clean up and return. */
- free (buffer);
- return len;
- }
-
-
- int
- print_widget_arginfo (const struct printf_info *info, size_t n,
- int *argtypes)
- {
- /* We always take exactly one argument and this is a pointer to the
- structure.. */
- if (n > 0)
- argtypes[0] = PA_POINTER;
- return 1;
- }
-
-
- int
- main (void)
- {
- /* Make a widget to print. */
- Widget mywidget;
- mywidget.name = "mywidget";
-
- /* Register the print function for widgets. */
- register_printf_function ('W', print_widget, print_widget_arginfo);
-
- /* Now print the widget. */
- printf ("|%W|\n", &mywidget);
- printf ("|%35W|\n", &mywidget);
- printf ("|%-35W|\n", &mywidget);
-
- return 0;
- }
复制代码
[ 本帖最后由 lemoncookie 于 2009-11-15 14:24 编辑 ] |
|