c++ - 我应该如何正确使用 g++ 的 -finput-charset 编译器选项来编译非 UTF-8 源文件?

标签 c++ gcc character-encoding g++

我正在尝试使用 -finput-charset 编译器选项在 g++ 中编译 UTF-16BE C++ 源文件,但我总是遇到一堆错误。更多详情如下。

我的环境(CentOS Linux):

  • g++: 4.1.2
  • 图标:2.5
  • Linux 语言(在终端中):LANG="en_US.UTF-8"

我的示例源文件(以 UTF-16BE 编码存储):

// main.cpp:

#include <iostream>

int main()
{
    std::cout << "Hello, UTF-16" << std::endl;
    return 0;
}

我的步骤:

  • 我阅读了 g++ 手册中关于 -finput-charset 选项的内容。 g++ 手册说:

-finput-charset=charset Set the input character set, used for translation from the character set of the input file to the source character set used by GCC. If the locale does not specify, or GCC cannot get this information from the locale, the default is UTF-8. This can be overridden by either the locale or this command line option. Currently the command line option takes precedence if there’s a conflict. charset can be any encoding supported by the system’s "iconv" library routine.

  • 于是我输入了如下命令:

g++ -finput-charset=UTF-16BE main.cpp

我得到了这些错误:

In file included from main.cpp:1:

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: error: stray ‘\342’ in program

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: error: stray ‘\274’ in program

...(repeatedly, A LOT, around 4000+)...

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: error: stray ‘\257’ in program

main.cpp: In function ‘int main()’:

main.cpp:5: error: ‘cout’ is not a member of ‘std’

main.cpp:5: error: ‘endl’ is not a member of ‘std’

  • 手册文本表明字符集可以是“iconv”例程支持的任何编码,因此我猜测编译错误可能是由我的 iconv 库引起的。然后我测试了iconv:

iconv --from-code=UTF-16BE --to-code=UTF-8 --output=main_utf8.cpp main.cpp

“main_utf8.cpp”文件按预期生成。然后我尝试编译它:

g++ -finput-charset=UTF-8 main_utf8.cpp

请注意,我明确指定了输入字符集以查看我是否做错了什么,但这次生成了“a.out”,没有任何错误。当我运行它时,它可以产生正确的输出。

最后...

我不知道我哪里做错了。我在网上搜索,试图找到此编译器选项的一些示例,但我找不到。

请指教!谢谢!

进一步编辑:

谢谢大家!您的回复很快!一些更新:

  1. 当我说“UTF-16”时,我的意思是“UTF-16 + BOM”。事实上,我使用的是 UTF-16BE。我已经更新了上面的文本。
  2. 有些回答说错误是由非 UTF-16 头文件引起的。如果是这种情况,我的想法是:在编写 C/C++ 项目时,我们总是会包含一些标准头文件,对吗?例如 stdio.h 或 iostream。如果 G++ 编译器只处理我们创建的源文件的编码,而不处理标准库中的源文件,那么这个 -finput-charset 选项存在的意义是什么??

最终编辑:

最后,我的解决方案是这样的:

  1. 开始时,我将源文件的编码更改为 GB2312,如下面的“Mr Lister”所述。有段时间还好用,后来发现不适合我的情况,因为系统中其他大部分还是用UTF-8来通信和接口(interface),所以很多地方都要转换编码... 不仅这是我工作的开销,它也可能导致我的程序性能下降。
  2. 后来我尝试将所有源文件转换为 UTF-8 + BOM。这样,Windows 中的 Visual Studio 可以愉快地编译它们,但 Linux 中的 GCC 会报错。然后我写了一个 shell 脚本来删除 BOM,在我想用 GCC 编译我的代码之前,我先运行这个脚本。
  3. 幸运的是,我不必在 Linux 中手动构建代码,因为我的项目中使用持续集成工具 TeamCity 自动生成构建。我可以更改 TeamCity 中的构建步骤,以帮助我在每日构建开始之前运行此脚本。
  4. 使用这种 UTF-8 + BOM + 脚本方法,我决定不在 Linux 中编辑我的源代码,因为如果我想这样做,我必须确保我的代码在提交之前能够成功构建,这意味着我在我构建代码之前必须运行脚本来删除 BOM,这意味着 SVN 会报告每个文件都被修改(BOM 已删除),因此很容易错误地提交错误的文件。为了解决这个问题,我写了另一个 shell 脚本来将 BOM 添加回源文件。虽然我仍然不经常在 Linux 中编辑我的代码,但当我真的需要时,我不必面对提交对话框中长得可怕的更改列表。

最佳答案

编码布鲁斯

源代码文件不能使用 UTF-16;因为您包含的 header <iostream> , 不是 UTF-16 编码的。作为#include逐字包含文件,这意味着您突然有了一个 UTF-16 编码的文件,其中包含大量无效数据(显然大约 4k)。

几乎没有充分的理由将 UTF-16 用于任何事情,所以这也无妨。

编辑:关于编码支持的问题:操作系统本身不负责提供编码支持,这取决于所使用的编译器。

Windows 上的 g++ 支持与 Linux 上的 g++ 完全相同的所有编码,因为它是同一个程序,除非您在 Windows 上使用的任何版本的 g++ 依赖于一个严重损坏的 iconv 库。

检查您的工具链并确保所有工具都正常工作。

作为替代方案;不要在源文件中使用中文,而是用英文编写,使用英文文字,或者简单的TOKEN_STYLE_PLACEHOLDER s,使用 l10ni18n在运行的可执行文件中替换它们。

Threedit: -finput-charset几乎可以肯定是代码页和其他类似废话时代的遗留问题;然而; ISO-8859-n 文件几乎总是与 UTF-8 标准 header 兼容,但是,请参阅下面的重新编辑。

Reedit: 为下次;记住一个简单的口头禅:“N'DUUH!”; “永远不要使用 UTF-8!”


I18N

此类问题的常见解决方案是完全消除问题,例如,gettext。 .

使用 gettext 时,通常会得到一个函数 loc(char *)抽象出大部分翻译工具特定的代码。所以,而不是

#include <iostream>

int main () {
  std::cout << "瓜田李下" << std::endl;
}

你会

#include <iostream>

#include "translation.h"

int main () {
  std::cout << loc("DEEPER_MEANING") << std::endl;
}

并且,在 zh.po :

msgid DEEPER_MEANING
msgstr "瓜田李下"

当然,你也可以有一个en.po :

msgid DEEPER_MEANING
msgstr "Still waters run deep"

这可以扩展,并且 gettext 包具有用于使用变量扩展字符串等的工具,或者您可以使用 printf , 以考虑不同的语法。


第三种选择

不必处理多个对文件编码、文件结尾、字节顺序标记和其他此类问题有不同要求的编译器;可以使用 MinGW 进行交叉编译或类似工具。

此选项需要一些设置,但可以很好地减少 future 的开销和麻烦。

关于c++ - 我应该如何正确使用 g++ 的 -finput-charset 编译器选项来编译非 UTF-8 源文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10345802/

相关文章:

c++ - 链接时优化和内联

c++ - 是否可以在 Mac OSX 10.6 中静态链接 libstdc++?

c++ - 列出目录 C++ 中的文件夹

c++ - 在 C++ 中将 int 转换为枚举的通用方法

c++ - 变量未按要求存储

gcc - 如何更改GCC编译器的目标目录?

安卓 NFC : 'd' prepended on NDEF payload

php - 使用 psql 插入到 postgres 数据库时的特殊字符

javascript - 比较 unicode 代码刻度线值

c++ - int min 的定点实现