smile unicode 的utf8编码是F0 9F 98 8A(十六进制表示)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[]) {
char * smile = " Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
因为smile[i]被自动提升为int型了。因为你的那些字节最高位都是1。所以提升时补1,打印的高位都是F。用%02X就可以了。
F09F988A 转成二进制:
11110000100111111001100010001010红色的是utf8的固定格式
每个字节的第一位数值是1,printf先把单字节转成
long(4字节),自动把左边多出来的字节用1填满。所以就打印出来 4字节的
FFFFFFxx%x的"一位"是十六进制的1个数字,也就是4bit / 半字节。这个符号的utf8表示真的就是4字节。不信你可以printf("%0x",* (unsigned int*)smile);c里变元函数的参数最短是int. 把char赋值给int时,左边补的位由char的最高位决定.
f0 9f 98 8a四个字节的高位都是1, 所以你会看到很多F (1111).另外
%x是给unsigned int用的, 打印1字节char可以用%hhx来忽略更高的位printf %什么与后面的参数应当完全匹配,否则行为未定义。以十六进制输出内存中的值应该
printf("%X", *(unsigned int *)smile);1个byte 8bit,用2个十六进制字符表示。
与Mysql字符集的collation算法有关。
MySQL 那个字符集的问题,我至今还没搞懂它为什么需要再加一个莫名其妙的 utf8mb4 「字符集」。也从没有听说别的使用 UTF-8 的软件需要对 U+10000 之后的字符进行特殊处理的。
只有使用 UCS-2,即两字节来表示字符的系统需要对这些字符特殊处理。比如 Windows、Java,好像 JavaScript 也是,内部使用的是 UTF-16,但是一些 API 里会把它当成 UCS-2 来处理,即认为编码是两字节定长的,导致对字符数量计算有误。