如何设置2字节的wchar_t输出?

问题描述 投票:4回答:2

GCC默认使用4字节的wchar_t。我可以设置选项-fshort-wcharwchar_t中获得每个L"string constants" 2个字节。但是当我将编译器选项设置为我的源文件时,我得到了着名的警告消息

foo.o使用2字节wchar_t但输出是使用4字节wchar_t;在对象中使用wchar_t值可能会失败

由于我真的想要2字节wchar_t,我也希望输出使用这个变体。是否有任何链接器选项告诉它我想要什么?

编辑

此警告不会禁止链接器生成有效输出。但是,数十个虚假警告涵盖了其他信息。

gcc ld binutils eabi
2个回答
10
投票

在binutils中,您可以在bfd/elf32-arm.c中找到以下错误消息:

“警告:%B使用%u-byte wchar_t但输出是使用%u-byte wchar_t;在对象之间使用wchar_t值可能会失败”

但是,如果你进一步研究binutils,你会发现输出的wchar_t大小在任何地方都没有被初始化为4。那么什么决定了“输出wchar_t大小”?实际上,给ld的第一个对象初始化了输出属性。下一个对象将其属性合并到其中。如果你用gcc / g ++链接,它会在内部执行ld,所以试试gcc -v并看看如何执行ld。这将使您深入了解内部对象文件(除了您自己的文件)隐式链接到您的可执行文件。

例如,与gcc(例如gcc -v -shared -o libfoobar.so foo.o bar.o)链接会导致调用:

ld ... crtbegin_so.o foo.o bar.o crtend_so.o ...

即实际链接以下对象(按顺序):

  • crtbegin_so.o(含蓄地)
  • foo.o的
  • 文件bar.o
  • crtend_so.o(含蓄地)

这是ld的作用:

  1. 输出属性集从空开始。
  2. 合并crtbegin_so.o属性。现在输出属性包含out_attr[Tag_ABI_PCS_wchar_t] == 4
  3. 合并foo.o属性。如果foo.o是用-fshort-wchar构建的,那么in_attr[Tag_ABI_PCS_wchar_t] == 2这将导致冲突和你所看到的警告。

如果您要在ld命令行上交换crtbegin_so.o和foo.o,则会收到以下警告:

ld:警告:android-ndk -r9d / platforms / android-16 / arch-arm / usr / lib / crtbegin_so.o使用4字节的wchar_t但输出是使用2字节的wchar_t;跨对象使用wchar_t值可能会失败

正如您所看到的,这不是输入与输出不兼容的问题,而是连接在一起的两个目标文件之间(感知)不兼容的问题。

我们对于它可以做些什么呢?

  • As of 2008ld支持--no-wchar-size-warning旗帜以抑制此警告。但正如你所说,不分青红皂白地压制警告有其缺点。
  • 您可以使用-fshort-wchar重建工具链。
  • 你可以从你的内部gcc对象二进制文件中剥离Tag_ABI_PCS_wchar_t标签,如果你真的相信它们是sizeof(wchar_t)-agnostic。这可能比重建工具链更容易。为此,你可以使用曾经写过的this utility。 (您可能需要解压缩libgcc.a,更改其目标文件并重新打包。)

-1
投票

这是一个警告,而不是错误。您可以忽略它,但如果您链接到使用4字节wchar_t编译的其他库,则会导致问题。如果你必须使用2字节的wchar_t,那么你将不得不找到这些库的替代品或重新编译它们

你也可以试试-fwide-exec-charset=UTF-16

  • -fwide-exec-charset=charset 设置宽执行字符集,用于宽字符串和字符常量。默认值为UTF-32或UTF-16,以wchar_t的宽度为准。与-fexec-charset一样,charset可以是系统的iconv库例程支持的任何编码;但是,您将遇到与wchar_t不完全匹配的编码问题。

如果你有C11支持,你可以使用char16_tu前缀为字符串文字)并在必要时转换为wchar_t

© www.soinside.com 2019 - 2024. All rights reserved.