首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc:-Wformat和register_printf_specifier的混合

gcc:-Wformat和register_printf_specifier的混合
EN

Stack Overflow用户
提问于 2015-03-20 06:09:01
回答 2查看 1.1K关注 0票数 1

我想使用自定义的printf格式标志(通过gcc的register_printf_specifier),同时仍然受益于-Wformat-Werror编译器标志。

在下面的示例中,我成功地使用自定义%W标志打印了我的小部件,但是我必须禁用-Wformat-Wformat-extra-args

代码语言:javascript
复制
#pragma GCC diagnostic ignored "-Wformat"
#pragma GCC diagnostic ignored "-Wformat-extra-args"

这两个世界都是有可能的吗?

我想我的问题归结为:是否有方法注册格式说明符和与-Wformat相关的类型?

示例:

代码语言:javascript
复制
#include <cstdio>
#include <cstdlib>
#include <printf.h>

struct Widget
{
    const char* name;
};

int print_widget(FILE* stream, const struct printf_info* info, const void* const* args)
{
    const Widget* widget = *((const Widget**)(args[0]));
    return fprintf(stream, "%*s", (info->left ? -info->width : info->width), widget->name);
}

int print_widget_arginfo(const struct printf_info*, size_t n, int* argtypes, int* size)
{
    if (n > 0)
    {
        argtypes[0] = PA_POINTER;
        size[0] = sizeof (Widget *);
    }
    return 1;
}

int main(void)
{
    register_printf_specifier('W', print_widget, print_widget_arginfo);

    Widget widget { "foobar" };

    #pragma GCC diagnostic ignored "-Wformat"
    #pragma GCC diagnostic ignored "-Wformat-extra-args"

    printf("|%W|\n", &widget);
    printf("|%35W|\n", &widget);
    printf("|%-35W|\n", &widget);
}

输出:

代码语言:javascript
复制
|foobar|
|                             foobar|
|foobar                             |
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-20 16:02:15

目前还没有这样的办法。见这个gcc虫

修改GCC以公开一些用于printf检查的内部机制并不太难,这样就可以编写一个能够理解您添加内容的GCC插件。不过,这确实需要对GCC有点熟悉。

票数 2
EN

Stack Overflow用户

发布于 2018-05-22 12:51:42

虽然没有直接的方法来注册针对-Wformat的新的说明符,但是有一种解决方法。您可以重载%p本身,并检测它是否应该是Widget*。这样做的一种方法是将一个特殊值编码到宽度中,并让您的说明符代码检测特定值。例如,

代码语言:javascript
复制
#define IS_WIDGET(INFO) (((INFO)->width & MASK) == WIDGET)

int print_widget(FILE* stream, const struct printf_info* info,
                 const void* const* args)
{
    if (IS_WIDGET(info)) return print_widget_impl(stream, info, args);
    return fprintf(stream, "%#*llx",
                   (info->left ? -info->width : info->width),
                   (unsigned long long)*(void **)args[0]);
}

概念的证明可以找到这里

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29160437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档