经典乱码“烫烫烫”和“屯屯屯”

12 篇文章 2 订阅

经典乱码“烫烫烫”和“屯屯屯”

转载参考自 https://blog.csdn.net/me4weizhen/article/details/51920343
转载参考自 https://blog.csdn.net/jarelzhou/article/details/19013037
转载参考自 https://blog.csdn.net/sinat_27382047/article/details/72810390

1. 烫烫烫屯屯屯

在 Visual Studio 中的 Debug 模式下,如果声明一个变量,但是没有初始化,微软会给未初始化的内存复制为 0xCC。给为初始化的内存赋 0xCC 是有原因的,0xCC 其实是 INT3 中断指令,所以如果在Debug 模式下试图去执行这块未初始化的内存的话就会中断程序。

但 VS 中调试器默认的字符集是 MBCS,而在 MBCS 中 0xCCCC (就是两个0xcc)正好就是中文 (一个汉字两字节) 中的“烫”,所以显示出来就都是烫……

如果是用分配堆的内存,会初始化成 0xCD,0xCDCD 在MBCS 字符集中就是屯……

演示代码:

#include<stdio.h>  
#include<malloc.h>  
int main()
{
	//烫烫烫
	char a[5];
	a[0] = 'a';//第一个赋了值
	printf("%s\n", a);

	//屯屯屯
	char *p = (char *)malloc(16);
	if (p)
		printf("%s", p);
	free(p);
	return 0;
}

运行结果:
Alt text

这种情况只有在 debug 模式下才会出现,为什么不适用于 release 模式,我的猜测是节省内存开销,此外 release 模式下声明一个变量却不初始化,这个变量中存放的应该是过去被使用的某个值。

2. 锟斤拷

锟斤拷则涉及 unicode 的字符集转换问题,Unicode和老编码体系的转化过程中,肯定有一些字,用 Unicode 是没法表示的,Unicode 官方用了一个占位符来表示这些文字,这就是
U+FFFD REPLACEMENT CHARACTER (译为 U+FFFD 替换字符)。

U+FFFD 的 UTF-8 编码是 0xEFBFBD (\xef\xbf\xbd),如果出现两个连着的 \xef\xbf\xbd\xef\xbf\xbd,按照两个字节一个字显示成汉字,就成了 锟斤拷 这三个字。

在 GBK/CP936/GB2312/GB18030 的环境(都是中国标准惹的祸)中显示的话,一个汉字 2 个字节,最终的结果就是:锟斤拷——锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)……

演示代码

#include<stdio.h>
int main()
{
	//锟斤拷
	char *a = "\xef\xbf\xbd\xef\xbf\xbd";
	printf("%s\n", a);

	//锘锘锘
	char *b = "\xef\xbb";
	printf("%s\n", b);
	return 0;
}

运行结果
Alt text

3. 锘锘锘原理

BOM 是 Byte Order Mark 的缩写。是 UTF 编码方案里用于标识编码的标准标记,在 UTF-16 里本来是FF FE,到 UTF-8 就成了EF BB BF。这个标记是可选的,因为 UTF8 字节没有顺序,所以它可以被用来检测一个字节流是否是 UTF-8 编码的。

锘 EFBB
匡 BFEF
豢 BBBF

出现这个问题肯定是你写网页的时候用了记事本 ,记事本在保存文件的时候把原本文件的编码改了记事本会默认保存为UTF-8 的编码,而如果你原本网页是 GBK 编码的,就会出现乱码~

BOM 就是把一个 Unicode 保留字符 U+FEFF,按照文件存储者的编码方式编码后,塞到文件内容的最前边。这样用不同的 Unicode 编码去解析文件头,就可以得知文件的编码方式和大小端顺序。结果就是文件头部多出来了两三个字节。

有了 BOM 所有的程序都必须为 BOM 作出修改,这无疑是一个“大折腾”的行为。所以一般不认为 BOM 是个好主意。BOM 引发的问题,我能想起来两个:

PHP无法指定header(因为有BOM相当于开启输出)
UNIX可执行脚本的Shabang标记(#!)不能识读

任何时候都采用无 BOM 的 UTF-8 编码的 Unicode,绝对是一个引发麻烦最少的最实用策略。UTF-8 是 Unicode 的最佳实践,没有之一。

必须指出的是,何弃疗的微软经常做出非要 DOM 不可的行为,最典型的例子就是那个记事本(存盘就加 DOM)。所以任何时候,都千万别偷懒用记事本编辑 PHP。华语骄傲 Notepad++ 是 Windows 下的不二之选。

PS: 锘锘锘这块的内容我并不是太理解,目前也没有太多时间深究,后续接触到这块内容的话会对博客进行补充。

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值