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

时间:2013-10-21 08:18:40

标签: gcc ld binutils eabi

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我也希望输出使用这个变体。是否有任何链接器选项告诉它我想要什么?

修改

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

2 个答案:

答案 0 :(得分:9)

在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会导致冲突以及您看到的警告。
  4. 如果您要在ld命令行上交换crtbegin_so.o和foo.o,则会收到以下警告:

      

    ld:警告:   机器人-NDK-r9d /平台/机器人-16 /拱形臂/ usr / lib中/ crtbegin_so.o   使用4字节的wchar_t但输出是使用2字节的wchar_t;用于   跨对象的wchar_t值可能会失败

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

    我们能做些什么呢?

    • As of 2008ld支持--no-wchar-size-warning标志以取消此警告。但正如你所说,不分青红皂白地压制警告有其缺点。

    • 您可以使用-fshort-wchar重建工具链。

    • 如果您真的相信他们是Tag_ABI_PCS_wchar_t - 不可知的话,您可以从内部gcc对象二进制文件中删除sizeof(wchar_t)标记。这可能比重建工具链更容易。为此,您可以使用我曾写过的this utility。 (您可能需要解压缩libgcc.a,更改其目标文件并重新打包。)

答案 1 :(得分:-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_t(字符串文字的u前缀)并在必要时转换为wchar_t