GCC默认使用4字节的wchar_t
。我可以设置选项-fshort-wchar
在wchar_t
中获得每个L"string constants"
2个字节。但是当我将编译器选项设置为我的源文件时,我得到了着名的警告消息
foo.o使用2字节
wchar_t
但输出是使用4字节wchar_t
;在对象中使用wchar_t
值可能会失败
由于我真的想要2字节wchar_t
,我也希望输出使用这个变体。是否有任何链接器选项告诉它我想要什么?
编辑
此警告不会禁止链接器生成有效输出。但是,数十个虚假警告涵盖了其他信息。
在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 ...
即实际链接以下对象(按顺序):
这是ld的作用:
out_attr[Tag_ABI_PCS_wchar_t] == 4
-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值可能会失败
正如您所看到的,这不是输入与输出不兼容的问题,而是连接在一起的两个目标文件之间(感知)不兼容的问题。
我们对于它可以做些什么呢?
ld
支持--no-wchar-size-warning
旗帜以抑制此警告。但正如你所说,不分青红皂白地压制警告有其缺点。Tag_ABI_PCS_wchar_t
标签,如果你真的相信它们是sizeof(wchar_t)
-agnostic。这可能比重建工具链更容易。为此,你可以使用曾经写过的this utility。 (您可能需要解压缩libgcc.a,更改其目标文件并重新打包。)这是一个警告,而不是错误。您可以忽略它,但如果您链接到使用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_t
(u
前缀为字符串文字)并在必要时转换为wchar_t