下一个案例:我有西里尔符号"б".运行下一个代码:
int main() {
char c;
scanf("%c", &c);
printf("%d\n", c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
显示-48.但是当我调试这个变量时c,它会显示下一个:-48 '\320'
.
那么这是如何工作的呢?这是一个指向2长度数组的指针吗?或者它如何存储两个数字?
甲char变量既可以被用来存储一个小1个在一些不那么良好定义的,通常-基于ASCII编码整数,或字符(更恰当地,代码单位).在这里,调试器只是试图通过显示内容的两个(有争议的)有意义的表示来提供帮助c.
让我们想象一下你实际上写的a而不是?; 在这种情况下,调试器会写类似的东西
c = {char} 97 'a'
Run Code Online (Sandbox Code Playgroud)
因为存储的实际数字c是97,并且解码为ASCII,它对应于字母a.
不幸的是,你可以将每个可能的字符放在一个8位char值中的想法是完全有缺陷的,因此现在使用的最广泛的编码(UTF-8)恰好是你机器上使用的编码,需要多个代码单位(≈bytes)表示单个代码点(≈逻辑字符)(此问题中的更多细节).特别地,б表示为两个字节的字符串,即字节0xD0和0xB1.
C对UTF-8或代码点一无所知; 如果指定%c为scanf,则它会读入单个字节,而不管它是否足以表示完整的UTF-8代码点.因此,只有第一个字节被读取,并且c只包含0xD0值; 0xB1仍在缓冲区中,尚未读取.
回到调试器显示的值,首先必须注意的是,在您的平台上(不幸的是,在许多平台上),char已签名.因此,0xD0字节被解释为带符号的值为-48(实际上,0xD0 = 208,其在127处"环绕"; 208-256 = -48).
至于'\320':这里的调试器想要显示该值的ASCII表示; 但是,字节0xD0在ASCII字符范围2之外,所以在这里它会显示一个转义序列.您可能熟悉'\n'代表换行符或\0NUL字符; 通常,\在C中后跟一到三位数表示具有相应八进制值的字节; 0320确实是208的八进制,对于0xD0是十进制的.
所以,这里没有任何谜:c仍然包含一个单独的值(只是你角色的"一半"); 你所看到的只是其内容的两个(同样不方便)的表示.
笔记
char(不幸的是,实现定义的)的签名.| 归档时间: |
|
| 查看次数: |
335 次 |
| 最近记录: |