【VC++开源代码栏目提醒】:网学会员为广大网友收集整理了,C++编译后的二进制程序中字符串的保存方式 - 编程语言,希望对大家有所帮助!
C/C编译后的二进制程序中字符串的保存方式 (小小程序员的软件之路 http://softwaredev.yo2.cn)【GCC 关于编译后字符串的保存方式的相关参数】先了解一下 GCC 关于编译后字符串的保存方式的参数。
GCC 编译时可以使用如下参数: -finput-charset 指定源文件的编码(若不指定,默认是 UTF-8) -fexec-charset 指定多字节字符串const char常量在编译后的程序里保存的编码集(若不指定, 默认是 UTF-8) -fwide-exec-charset 指定宽字节字符串const wchar_t常量在编译后的程序里的保存的编码集如:gcc TestMain.cpp -g -lstdc -finput-charsetGB2312 -fexec-charsetGB2312【源
代码中含有宽字节字符串的情况】测试
代码: TestMain.cpp 编码:GB2312void ShowBufferconst char prompt const void buffer size_t bufferSize printfs: prompt const unsigned char byteBuffer const unsigned charbuffer size_t i for i 0 i bufferSize i printf02x byteBufferi printfnint mainvoid char str 中文 wchar_t wstr L中文 ShowBufferstr str sizeofstr ShowBufferwstr wstr sizeofwstr return 0下面列出的是不同环境下编译后的运行结果:1. Windows 1
VC6.0 编译: str: d6 d0 ce c4 00 wstr: 2d 4e 87 65 00 002 Linux GCC 第1页/共5页 http://softwaredev.yo2.cn/ 1 gcc TestMain.cpp -lstdc TestMain.cpp:24:19: converting to execution character set: Invalid or incomplete multibyte or wide character 第 24 行的内容为“wchar_t wstr L中文”) 2 gcc TestMain.cpp -lstdc -finput-charsetGB2312 str: e4 b8 ad e6 96 87 00 wstr: 2d 4e 00 00 87 65 00 00 00 00 00 00 3 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 str: d6 d0 ce c4 00 wstr: 2d 4e 00 00 87 65 00 00 00 00 00 00 4 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwide-exec-charsetGB2312 str: d6 d0 ce c4 00 wstr: d6 d0 ce c4 00 00 00 00 5 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwide-exec-charsetUCS-4BE str: d6 d0 ce c4 00 wstr: 00 00 4e 2d 00 00 65 87 00 00 00 003 SUN SPARC Solaris 1 gcc TestMain.cpp -lstdc TestMain.cpp:24:19: converting to execution character set: Illegal byte sequence 2 gcc TestMain.cpp -lstdc -finput-charsetGB2312 str: e4 b8 ad e6 96 87 00 wstr: 00 00 4e 2d 00 00 65 87 00 00 00 00 3 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 str: d6 d0 ce c4 00 wstr: 00 00 4e 2d 00 00 65 87 00 00 00 00 4 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwide-exec-charsetGB2312 str: d6 d0 ce c4 00 wstr: d6 d0 ce c4 00 00 00 00 5 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwide-exec-charsetUCS-4BE str: d6 d0 ce c4 00 wstr: 00 00 4e 2d 00 00 65 87 00 00 00 00 6 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwi de-exec-charsetUCS-2LE str: d6 d0 ce c4 00 wstr: 2d 4e 87 65 00 00 00 00 通过上面的结果我们可以得到如下结论: Windows 下编译出来的程序, 1 对于多字节字符串, 字符串在编译后的程序里的存储编码与源
代码相同: 源
代码是 GB2312,则编译后的
代码也是 GB2312; 2 对于宽字节字符串,Windows 总是在编译时,根据编译机器的字符集设置,将源
代码中的多字节字符 串转换成 UnicodeUCS2-LE; 第2页/共5页 http://softwaredev.yo2.cn/ 3 而在 Linux 下,源
代码的字符集由参数-finput-charset 参数决定 4 在 Linux 下,如果源
代码中出现了宽字节字符串常量,则在编译时必须带“-finput-charset”参数 和“-fexec-charset 参数”;而“-fwide-exec-charset 参数可以省略”(省略该参数时,默使用 UCS-4LE 的 Unicode 编码保存); 5 Linux 下可以使用“-fexec-charset”参数来指定二进制程序中,多字节串的字符集,这样,编译后 的二进制程序的字符集可以和源
代码的字符集不一样。
6 Solaris 下的情况和 Linux 非常相似,只是在省略“-fwide-exec-charset”参数时,默认使用的编码 是 UCS-4BE 的 Unicode 编码。
【源
代码中不含有宽字节字符串的情况】我们将
代码中有关宽字节字符串的
代码(也即与 wstr 相关的
代码)都去掉。
看看在不同的环境会有什么样的运行结果:1 Windows 1
VC6.0 编译: str: d6 d0 ce c4 002 Linux GCC 1 gcc TestMain.cpp -lstdc (这回编译成功了) str: d6 d0 ce c4 00 2 gcc TestMain.cpp -lstdc -finput-charsetGB2312 str: e4 b8 ad e6 96 87 00 3 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetUTF-8 str: e4 b8 ad e6 96 87 00 4 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 str: d6 d0 ce c4 003 SUN Sparc Solaris 1 gcc TestMain.cpp -lstdc 这回可以编译通过了 str: d6 d0 ce c4 00 2 gcc TestMain.cpp -lstdc -finput-charsetGB2312 str: e4 b8 ad e6 96 87 00 3 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetUTF-8 str: e4 b8 ad e6 96 87 00 4 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 str: d6 d0 ce c4 00 根据上面的运行结果,我们可以得出如下结论: 1 在 Linux 和 Solaris 下,当源
代码中没有包含宽字节字符的常量时,使用 gcc 编译时可以不需要 “-finput-charset”参数和“-fexec-charset 参数”,默认使用和源
代码相同的字符集保存多字节 字符串; 2 在 Linux 和 Solaris 下,当源
代码中没有包含宽字节字符串时,仍然可以通过上述两个参数来指示编 译后的二进制程序里的字符串的字符集和源
代码的不同; 通过上述两个参数指示二进制程序里的字符串以 UTF-8 的字符集保存字符串, 3 在 Linux 和 Solaris 下, 这样,在 UTF-8 的输出终端下,就可以支持直接输出任何国家的Unicode字符了。
第3页/共5页 http://softwaredev.yo2.cn/【SPRINTF 存储测试】 下面的这个测试,用于测试使用 sprintf 函数将一个字符串输出到一个缓冲区时,不同的编译环境下 会有怎样的表现。
原来的测试
代码修改成: TestMain.cpp 编码:GB2312ifdef _MSC_VERdefine swprintf _snwprintf //统一
VC 下的 swprintf 和 ISO C 的相同endifint mainvoid char str 中文 wchar_t wstr L中文 char buffer64 wchar_t wbuffer64ifdef _MSC_VER setlocaleLC_ALL chselse setlocaleLC_ALL zh_CN.GB2312endif //_MSC_VER sprintfbuffer s str ShowBufferbufferstrs buffer strlenbuffer sprintfbuffer ls wstr ShowBufferbufferwstrls buffer strlenbuffer swprintfwbuffer 64 Ls str ShowBufferwbufferstrs wbuffer wcslenwbuffer sizeofwchar_t swprintfwbuffer 64 Ls wstr ShowBufferwbufferwstrs wbuffer wcslenwbuffer sizeofwchar_t swprintfwbuffer 64 Lls wstr ShowBufferwbufferwstrls wbuffer wcslenwbuffer sizeofwchar_t return 0不同的编译环境下会有如下不同的结果:1 Windows 1
VC 6.0 编译: bufferstrs: d6 d0 ce c4 bufferwstrls: d6 d0 ce c4 wbufferstrs: d6 d0 ce c4 00 cc cc cc c0 ff 13 00 e9 20 40 00 01 00 wbufferwstrs: 2d 4e 87 65 wbufferwstrls: 2d 4e 87 652 Linux 1 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 bufferstrs: d6 d0 ce c4 bufferwstrls: d6 d0 ce c4 第4页/共5页 http://softwaredev.yo2.cn/ wbufferstrs: 2d 4e 00 00 87 65 00 00 wbufferwstrs: 2d 00 00 00 4e 00 00 00 wbufferwstrls: 2d 4e 00 00 87 65 00 00 2 gcc TestMain.cpp -lstdc -finput-charsetGB2312 -fexec-charsetGB2312 -fwide-exec-charsetUCS-2LE bufferstrs: d6 d0 ce c4 bufferwstrls: wbufferstrs: 25 00 73 00 wbufferwstrs: 25 00 73 00 wbufferwstrls: 25 00 6c 00 73 00 00 00 00 00 77 62 75 66 66 65 72 5b 77 73 74 72 28 25 6c 73 29 5d根据上面的
代码,我们可以得出以下的结论: 1 sprintf 可以输出多字节串(使用s),也可以输出宽字节串(使用ls)。
sprintf 最终会将字符串 以多字节串的形式保存到 buffer 中,而这个宽字符串到多字节串的转换依赖于 setlocale 函数所设 置的本地化环境中的字符集设置。
2 在 Linux 下绝对不能使用“-fwide-exec-charset”改变宽字节串的默认存储方式,否则 sprintf 将 无法正确的将宽字节串转换成对应的多字节串。
3 对于 wprintf 中的s,在
VC 下表示宽字节串,在 GCC 下表示多字节串。
4 Solaris 下的 GCC 和 Linux 下的 GCC 情况基本相同; 第5页/共5页 http://softwaredev.yo2.cn/
上一篇:
一个php的分页类(含调用方法)
下一篇:
西班牙语童话:El Alimento de Dios