跨平台C程序中Unicode方框绘制字符在MinGW+Cygwin终端显示异常求助
问题背景
我需要开发一款跨操作系统、兼容不同C编译环境的程序,其中使用了Unicode方框绘制字符,示例代码如下:
#include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { printf ("┌─────┐\n"); printf ("│┼┼┼┼┼│\n"); printf ("└─────┘\n"); return EXIT_SUCCESS; }
该代码在以下环境中均可正常显示预期的方框图形:
- Linux(gcc/icc)
- Windows WSL(gcc)
- Windows下Cygwin gcc(命令提示符及Cygwin终端)
- Windows MinGW(命令提示符)
但MinGW编译的程序在Cygwin终端中显示乱码,乱码内容:
ÔöîÔöÇÔöÇÔöÇÔöÇÔöÇÔöÉ ÔöéÔö╝Ôö╝Ôö╝Ôö╝Ôö╝Ôöé ÔööÔöÇÔöÇÔöÇÔöÇÔöÇÔöÿ
已排除Cygwin终端字体问题(Cygwin gcc编译的同程序在该终端显示正常,且MinGW程序在Windows命令提示符中显示正常)。使用的Windows编译器版本:
gcc (MinGW.org GCC-6.3.0-1) 6.3.0 gcc (GCC) 11.3.0 - with Cygwin
解决方法
1. 强制程序输出UTF-8编码
MinGW默认会把字符串按照Windows本地编码(通常是GBK/GB2312)输出,而Cygwin终端默认使用UTF-8编码,编码不匹配导致乱码。可以通过以下方式强制程序输出UTF-8:
方法A:使用setlocale设置UTF-8 locale
修改代码,添加locale设置:
#include <stdio.h> #include <stdlib.h> #include <locale.h> int main (int argc, char *argv[]) { // 设置为UTF-8 locale setlocale(LC_ALL, "en_US.UTF-8"); printf ("┌─────┐\n"); printf ("│┼┼┼┼┼│\n"); printf ("└─────┘\n"); return EXIT_SUCCESS; }
编译时无需额外参数,运行后Cygwin终端即可正常显示。
方法B:直接输出UTF-8字节序列
如果不想依赖locale设置,可以将方框字符替换为对应的UTF-8字节转义序列:
#include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { // ┌ 的UTF-8是 0xE2 0x94 0x8C,─是0xE2 0x94 0x80,┐是0xE2 0x94 0x90 printf ("\xE2\x94\x8C\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x90\n"); // │是0xE2 0x94 0x82,┼是0xE2 0x94 0xBC printf ("\xE2\x94\x82\xE2\x94\xBC\xE2\x94\xBC\xE2\x94\xBC\xE2\x94\xBC\xE2\x94\xBC\xE2\x94\x82\n"); // └是0xE2 0x94 0x94,┘是0xE2 0x94 0x98 printf ("\xE2\x94\x94\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x80\xE2\x94\x98\n"); return EXIT_SUCCESS; }
这种方式不依赖系统locale,兼容性更强,适合跨平台场景。
2. 编译时指定字符编码
MinGW的gcc支持通过-fexec-charset=UTF-8参数指定程序运行时的输出字符编码,编译命令改为:
gcc -o box box.c -fexec-charset=UTF-8
编译后的程序在Cygwin终端中会直接输出UTF-8编码的字符,无需修改代码。
原理说明
MinGW作为Windows原生编译工具,默认使用Windows的系统默认编码(如GBK)处理字符串常量;而Cygwin终端模拟类Unix环境,默认采用UTF-8编码。当MinGW编译的程序输出GBK编码的方框字符时,Cygwin终端以UTF-8解码就会出现乱码。上述方法本质都是让程序输出UTF-8编码,匹配Cygwin终端的解码方式。
内容的提问来源于stack exchange,提问作者Peter McGavin

