[讨论] GCC与unicode - 跨平台字符串支持

suemiineo 2012-10-11 11:21:09
HI, 大家好

小生很有意开发一套工具库 由于牵涉到跨平台和效率问题 我使用了纯C语言来编写

但是在处理字符串的问题上 楼主忽然头大了 因此我很希望能和大家分享我遇到的问题


问题 1) utf-8在检索上的小小问题

众所周知 utf-8能很好地兼容POSIX程序接口 而且也利于存储和网络传输 但是在检索多字节字符上却遭遇小小瓶颈

假如有utf-8的字符串 "我们都是程序猿"

但是我们却不能检索在这个字符串中的某个字符 如'程' 而必须将 程 字当做一个字符串来处理 如"程"


问题 2) 向wchar过度 却遭遇内存瓶颈

为了解决问题1) 就只能向wchar求助 但是wchar在linux c中是定义为4字节的 而通常情况下 大多数字符串都只需要两个字节就足够了 而对于utf-32来说 几乎要使用两倍的内存来保存相同内容的utf-16的字符串 这无疑是极大浪费

参考到当下比较知名的库和托管类语言的解决方案 列表如下

windows - utf-16
java - utf-16
c# - utf-16
Qt - utf-16
glib - utf-8

因此我不是很理解为何linux c偏偏使用utf-32的unicode


问题 3) 即使使用wchar还是要重写io接口

即使决定在linux下使用wchar 还有字符串打印的问题需要解决 因此在标准io接口中是区分宽窄字符的

如wprintf(L"我们都是%ls", L"程序") //注意使用的格式化输出是%ls

假如我们想使用C标准的简洁模式 却不得不实现本地化的printf


问题 4) 构建本地utf-16系统 却遭遇编译器瓶颈

为了解决以上的问题 最直接的办法就是开发一套自适应的字符串库

即将本地的字符类定义为2字节 即使需要重写整套io的接口都不是很大问题 但最大的问题却在编译器上

因为当下的GCC版本无法接受utf-16的字符串字面量

并且当前C环境下没有任何办法将Utf-32或utf-8的字符串字面量直接转换为utf-16


问题 5) 回到问题最初 unicode真的值得吗

实现想不到一个wchar就会引出如此之多的问题 这不禁让我想到问题最初 我们真的需要unicode吗

或许基于utf-8的ansi c就足够了呢

顺便提一点 glib使用的是utf-8


楼主一下子想到了很多 恐怕在下在技术上还有很大疏漏 因此不排序楼主在某些地方确实想多了

因此楼主将这些问题列举出来 供大家一起思考


...全文
660 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Pluto__Hades 2013-04-27
  • 打赏
  • 举报
回复
我们跨平台项目中的做法我这里稍微抛砖引玉 typedef char U8Char; typedef unsigned short U16Char; typedef unsigned int U32Char; 自行实现各种字符串处理类和函数,使用iconv或者icu实现代码页转换。不过如果只是UTF8、16、32之间互转都不用码表的。 不同的环境没有什么特效药,通过#if、#ifdef、#ifdefined检测编译器和系统的预定义宏来判断平台,决定默认的字符串处理模式。微软的Visual Studio就是通过检查UNICODE宏来决定生成的字符串。 善用预编译指令就可解决跨平台问题。GNU的很多跨平台项目就是这个干的。 目前常见的编译器也就Windows平台的微软、Intel、mingw gcc、cygwin gcc MacOS 的xcode、gcc Linux的gcc 最近兴起的llvm基本兼容gcc,问题不大。
赵4老师 2012-12-24
  • 打赏
  • 举报
回复
网络用utf8一个汉字三个字节效率够高吗?
赵4老师 2012-10-11
  • 打赏
  • 举报
回复
问题1)L'程'在内存中如果用utf8编码占3个字节。
问题2)linux c可以使用utf-16
问题3)wprintf需要事先setlocale
问题4)自己编写Utf-32或utf-8的字符串字面量直接转换为utf-16
问题5)不妨写一个同时显示中文简体、中文繁体、韩文、日文、阿拉伯文的记事本试试
suemiineo 2012-10-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

问题1)L'程'在内存中如果用utf8编码占3个字节。
问题2)linux c可以使用utf-16
问题3)wprintf需要事先setlocale
问题4)自己编写Utf-32或utf-8的字符串字面量直接转换为utf-16
问题5)不妨写一个同时显示中文简体、中文繁体、韩文、日文、阿拉伯文的记事本试试
[/Quote]

多谢回复 不过我所面临的问题恐怕比这个更加复杂

我举个例子

对于 问题2)的补充

// 代码2.1)
//假设当前运行环境是LINUX C, 并且我需要一个抽象字符类型(在这里暂且使用TCHAR), 则
typedef wchar_t TCHAR; //utf-32
typedef char // utf-8

#define TEXT(t) L##t // utf-32
#define TEXT(t) t //utf-16

现在TCHAR可能有两种不同的定义 但是我们希望最终呈现给用户的字符集接口只有一种并且同时兼容两种模式
则我们如何才能够令到以下代码在两种环境下都正常运行呢?

// 代码2.2)
//假设我们定义了TPrintf函数,则有
TPrintf(TEXT("%s"), TEXT("abcd"));

如果对比C的标准库说明就会知道代码2.2)只有在ansi环境下能正常输出 而在unicode环境下就会出错

因为C99之前就规定在格式化输出字符串时要区分两种格式%s(ansi字符) %ls(unicode字符)具体参考
http://en.cppreference.com/w/c/io/fprintf

因此导致TCHAR接口统一抽象性遭到破坏

另外 问题4)还想补充一些内容
加入说我们要抛开wchar_t的定义 自定义TCHAR 如
typedef signed short TCHAR;
但是在初始化字符串字面量的情况下就会遭遇困窘

// 代码4.1)
const TCHAR * str = TEXT("我们都是程序猿");

这里TEXT只有两种定义L"xxx"(utf-32) "xxx"(utf-8)
如果将TEXT宏hack一下 通过一个内部函数来将这两种方式进行转换 的确可以 但是转换需要用到公共内存区 在多线程的环境下又会遭遇窘迫

参照最新的C++11的标准 由此引入了一个十分重要的定义 即允许直接定义utf-16字面量
u"This is a UTF-16 string."
具体请参考http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals
因此只需要将TEXT重新定义为

//代码4.2)
#define TEXT(t) u##t


最后 问题3) 再补充一点

如果是工作在linux c下几乎不会用到宽字符的打印函数 我只想举个例子说明在格式化输出上的差异

如果硬要输出wchar 的确会遇到楼主说的locate问题

当前小生认为较为妥当的处理流程为

文件,网络输入(utf-8) -> 程序逻辑内部(utf-16/32) -> 打印,存储,网络传输(utf-8)

也就是说字符串几乎是需要进行转换的 当保存为文件或发送到网络的时候(为了节省空间和流量)通常将字符串保存为utf-8格式 但是读入程序内部处理的时候需要转换为utf-16/32 然后打印或者重新保存,发送时又再转换回utf-8

文献http://www.linuxforum.net/books/UTF-8-Unicode.html
当中就曾谈到这种实现方式 并且我相信目前大部分系统都是这样实现的
Code::Blocks 是一个开放源码的全功能的跨平台C/C++集成开发环境.   相比于基于Delphi的Dev-C++共享C++IDE,Code::Blocks是开放源码软件。Code::Blocks由纯粹的C++语言开发完成,它使用了蓍名的图形界面库wxWidgets(2.6.2 unicode)版。对于追求完美的C++程序员,再也不必忍受Eclipse的缓慢,再也不必忍受VS.NET的庞大和高昂的价格。   虽然Code::Blocks从一开始就追求跨平台目标,但是最初的开发重点是Windows 系统下的版本,从06年3月21日版本:1.0 revision 2220开始,Code::Blocks在它的每日构建中正式提供Linux版本(分两个版本:ubuntu.deb和fc4.rpm)。这样 Code::Blocks在1.0发布时就会是跨越平台的C/C++IDE,它将支持Windows和Linux的主要版本。长期以来C++开发员在 Linux没有好用、通用的C++ IDE的局面就要结束。而这个IDE对于Windows下的用户同样重要,由于它开放源码的特点,Windows用户可以不依赖于VS.NET,编写跨平台C++应用。   Code::Blocks提供了许多工程模板,这包括:控制台应用、DirectX应用、动态连接库、FLTK应用、GLFW应用、Irrlicht工程、OGRE应用、OpenGL应用、QT应用、SDCC应用、SDL应用、SmartWin应用、静态库、Win32 GUI应用、wxWidgets应用、wxSmith工程,另外它还支持用户自定义工程模板。在wxWidgets应用中选择UNICODE支持中文。   Code::Blocks支持语法彩色醒目显示,支持代码完成(目前正在重新设计过程中)支持工程管理、项目构建、调试。   Code::Blocks支持插件,目前的插件包括代码格式化工具AStyle;代码分析器;类向导;代码补全;代码统计;编译器选择;复制字符串到剪贴板;调试器;文件扩展处理器;Dev-C++ DevPak更新/安装器;DragScroll,源码导出器,帮助插件,键盘快捷键配置,插件向导;To-Do列表;wxSmith;;wxSmith MIME插件;wsSmith工程向导插件;WindowsXP外观。   Code::Blocks具有灵活而强大的配置功能,除支持自身的工程文件、C/C++文件外,还支持AngelScript、批处理、CSS文件、D语言文件、Diff/Patch文件、Fortan77文件、GameMonkey脚本文件、 Hitachi汇编文件、Lua文件、MASM汇编文件、Mathlab文件、NSIS开源安装程序文件、Ogre Compositor脚本文件、Ogre Material脚本文件、OpenGL Shading语言文件、Python文件、Windows资源文件、XBase文件、XML文件、nVidia cg文件。识别Dev-C++工程、MS VS 6.0-7.0工程文件,工作空间、解决方案文件。   Code::Blocks基于wxWidgets开发,正体现了wxWidgets的强大。以前Borland C++ Builder X宣称基于wxWidgets开发跨平台、兼容性好、最优秀的C++ IDE环境,但没有实现;现在Code::Blocks+GNU GCC正在实现这个理想。让我们拭目以待。国内的Code::Blocks爱好者和跨平台开发员应该尽快建立中文Code::Blocks网站,提供 Code::Blocks中文化支持,促进Code::Blocks在国内的发展。 --- 摘自百度百科(http://baike.baidu.com/view/1562377.htm)

70,019

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧