调用 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<const char*>(smiley)
。
【讨论】:
另一个变体是有一个c_str()
成员(就像std::string
一样)。
Microsoft 的CString
使用char*
作为第一个成员的布局,以允许printf
在没有演员表的情况下工作,但他们也说你最好转换它以获得预期的结果 - @987654321 @
@A.A 这也是非常特定于实现的,并且很大程度上取决于编译器如何实现可变参数。
我同意这个答案,但我还不想接受它,因为也许有人会想出一个漂亮的解决方法或其他一些简单的方法
我最终为 gui 函数添加了一个重载,该函数接受 icon
并使用静态转换调用原始 API...以上是关于调用 printf 时隐式转换为 char*的主要内容,如果未能解决你的问题,请参考以下文章
为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除构造函数
Java - 为啥 char 不应该被隐式转换为字节(和短)原语?
为啥仅在某些情况下才能将字符串文字隐式转换为 char* ? [复制]
RuntimeError: GPU:0 上的 CUDA 运行时隐式初始化失败。状态:所有支持 CUDA 的设备都忙或不可用