调用 printf 时隐式转换为 char*

Posted

技术标签:

【中文标题】调用 printf 时隐式转换为 char*【英文标题】:Implicit cast to char* when calling printf 【发布时间】:2018-01-04 08:57:57 【问题描述】:

我在我的 C++ GUI 应用程序中使用 Unicode 字符串作为图标,并希望摆脱我散落的所有 u8"\uf118" 魔术字符串,并在途中使这些字符串成为自己的类型。

所以我创建了一个这样的类:

struct icon

    explicit constexpr icon(const char (&unicode_icon)[4]) :
        _icon unicode_icon[0], unicode_icon[1], unicode_icon[2], unicode_icon[3] 
    
    
    operator const char*() const
    
        return _icon.data();
    
private:
    std::array<char, 5> _icon;
;

GUI 库使用某种形式的printf(我认为是vfprintf) 所以代码调用:

icon smiley  u8"\uf118" ;
printf("%s", smiley);

到目前为止,我在 Windows 上对此进行了测试,效果很好,但是当我在 Linux 上使用 gcc (5.1) 编译它时,我收到以下警告:

main.cpp:22:24: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'icon' [-Wformat=]
     printf("%s", smiley);

Live example here

当我运行它时,我在vfprintf 中遇到了一个段错误,因为它没有使用我提供的强制转换运算符。

我知道当我将图标传递给 GUI 库时我可以显式地转换它(它具有以下原型 (const char* fmt, ...) 但这会让我编写更多代码,而且看起来会更糟。

有没有办法让编译器发挥作用并允许我像这样调用函数:printf("%s", smiley);(或其他一些简单的方法)?

【问题讨论】:

嗯,为什么?为什么需要上课?为什么不const char* smiley = u8"\uf118"; 如果它在 Windows 上工作,那只是一个意外,明天不一定能工作。 或者,在紧要关头,const std::string smileyu8"\uf118"; 这些东西毕竟是字符串。 printf() 是一个可变参数函数。格式说明符告诉函数如何解释它接收到的相应参数。它不会告诉编译器为了将对象作为参数传递而转换为指定的类型。 @n.m. const std::string smiley 将运行时开销添加到以前只是 printf("%s", u8"\uf118") 的代码中 【参考方案1】:

C++ 不能很好地处理可变参数函数。最重要的是,没有隐式转换对象,因为编译器(在一般情况下)无法知道真正期望的类型。

如果有替代方案,最好的解决方案是使用可变参数函数。对于printf 和朋友,有(对于printf 它是std::cout)。

如果您出于某种原因仍需要使用可变参数函数(例如因为您使用 C 库),那么唯一的解决方案是显式转换对象。在您的情况下,它将是 static_cast&lt;const char*&gt;(smiley)

【讨论】:

另一个变体是有一个c_str() 成员(就像std::string 一样)。 Microsoft 的CString 使用char* 作为第一个成员的布局,以允许printf 在没有演员表的情况下工作,但他们也说你最好转换它以获得预期的结果 - @987654321 @ @A.A 这也是非常特定于实现的,并且很大程度上取决于编译器如何实现可变参数。 我同意这个答案,但我还不想接受它,因为也许有人会想出一个漂亮的解决方法或其他一些简单的方法 我最终为 gui 函数添加了一个重载,该函数接受 icon 并使用静态转换调用原始 API...

以上是关于调用 printf 时隐式转换为 char*的主要内容,如果未能解决你的问题,请参考以下文章

可以在编译时隐式引用类名吗?

为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除​​构造函数

将 CString 隐式转换为 char*

Java - 为啥 char 不应该被隐式转换为字节(和短)原语?

为啥仅在某些情况下才能将字符串文字隐式转换为 char* ? [复制]

RuntimeError: GPU:0 上的 CUDA 运行时隐式初始化失败。状态:所有支持 CUDA 的设备都忙或不可用