chr()仅支持0–255单字节ASCII字符,传入20013等Unicode码位会归约为chr(173)输出乱码;中文或emoji需用mb_chr()或IntlChar::chr()。

chr() 只能生成单字节字符,别指望它直接输出中文或 emoji —— 它压根不处理 UTF-8 码位,传 20013 会变成 chr(0),不是“中”。
chr() 的参数范围和溢出行为
参数 $codepoint 名义上应是 0–255 的整数,但 PHP 实际做了容错处理:
- PHP 7.4 之前:超出范围的值(如
-159或833)会自动按位与 255,等价于$codepoint % 256(负数先加 256 直到非负) - PHP 7.4+:仍会做归约,但官方已标记「传非 0–255 值」为 deprecated(PHP 8.5.0 起正式弃用)
- 常见误用:
chr(65)→"A"没问题;chr(20013)→ 实际执行chr(20013 % 256)=chr(173),结果是 Latin-1 中的软连字符,不是汉字
怎么安全地生成 ASCII 字符(如字母、控制符)
明确限定在 0–255 内,且目标编码是 ASCII 兼容单字节编码(如 Windows-1252)时,chr() 才可靠:
- 大写字母:
chr(65)到chr(90) - 小写字母:
chr(97)到chr(122) - 换行/回车:
chr(10)(LF)、chr(13)(CR),组合用chr(13).chr(10) - ESC 控制符:
chr(27),常用于终端转义序列 - 避免硬写数字:用十六进制更清晰,比如
chr(0x21)(!)、chr(0x41)(A)
为什么 chr(240).chr(159).chr(144).chr(152) 能输出 ?
这不是 chr() 支持 Unicode,而是你手动拼出了 UTF-8 编码的四个字节:
立即学习“PHP免费学习笔记(深入)”;
- U+1F40E(?)的 UTF-8 编码就是
0xF0 0x9F 0x90 0x98,即十进制240、159、144、152 -
chr()只负责把每个数字转成对应字节,拼起来后由终端或浏览器按 UTF-8 解码 —— 函数本身完全不知情 - 风险:若环境编码不是 UTF-8(如 ISO-8859-1),这串字节会显示为乱码或问号
- 真正需要 Unicode 码位映射?用
mb_chr(128014)(需启用 mbstring)或IntlChar::chr(128014)
容易被忽略的兼容性陷阱
看似简单的函数,实际踩坑点很隐蔽:
- Web 输出时,
chr(13)和chr(10)在 HTML 中不会换行,得配合<br>或 CSSwhite-space: pre - Windows 下写文件用
chr(13).chr(10),Linux/macOS 用chr(10),混用可能造成 Git 提示 CRLF/LF 不一致 - 数据库存储前没过滤
chr(0)(空字节),某些驱动或字段类型会截断字符串 - 用
sprintf("%c", $n)替代chr($n)更安全 —— 它对超范围值的行为更稳定,且语义更清晰



















