【问题标题】:Can %c be given a negative int argument in printf?可以在 printf 中给 %c 一个负的 int 参数吗?
【发布时间】:2020-08-22 22:09:37
【问题描述】:

我可以在通过格式说明符%c 打印时在printf 中传递一个负整数,因为在打印int 时会转换为无符号字符? printf("%c", -65); 有效吗? — 我在 GCC 上尝试过,但得到了一个类似菱形的字符(里面有问号)作为输出。为什么?

【问题讨论】:

  • 如果您打印值 -65,您希望使用哪种表示形式? char 类型不仅用于存储可打印字符。它也是一种相当短的数值类型。

标签: c char int printf negative-number


【解决方案1】:

如果char 是有符号类型,则绝对可以。 C 允许 chareither signed or unsigned,在 GCC 中,您可以使用 -funsigned-char and -fsigned-char 在它们之间切换。当 char 被签名时,它与 this 完全相同

char c = -65;
printf("%c", c);

当传递给printf() 时,char 变量将被符号扩展int,因此printf() 也会看到 -65,就像它是从常量传递的一样。 printf 根本无法区分 printf("%c", c);printf("%c", -65);,因为 default promotion 在可变参数函数中。

打印结果取决于字符编码。例如,在ISO-8859-1Windows-1252 字符集中,您会看到¿,因为(unsigned char)-65 == 0xBF。在 UTF-8(这是一种可变长度编码)中,不允许 0xBF 作为起始位置的字符。这就是为什么您会看到 � 它是无效字节的替换字符

请告诉我为什么代码点 0 到 255 没有映射到 unsigned char 中的 0 到 255。我的意思是它们是非负数,所以我不应该只查看 UTF-8 字符集的对应值吗?

映射并不是像你想象的那样通过范围内的相对位置来完成,即代码点0映射到CHAR_MIN,代码点40映射到CHAR_MIN + 40,代码点255映射到CHAR_MAX...在二进制补码系统它通常是一个简单的映射,当被视为无符号时,它基于 位模式 的值。这是因为值通常从更广泛的类型截断的方式。在 C 中,像 'a' 这样的字符文字具有 int 类型。假设'a' 映射到某个理论字符集中的代码点 130,那么下面的行是等价的

char c = 'a';
char c = 130;

无论哪种方式,c 在转换为 char 后都会被赋值为'a',即(char)'a',这可能是一个负值

所以代码点 0 到 255 映射到 unsigned char 中的 0 到 255。这意味着代码点代码点 0x1F 将存储在值为 0x1F 的字符(有符号或无符号)中。如果 char 是无符号的,代码点 0xBF 将映射到 0xBF,如果 char 是有符号的,则映射到 -65

我假设以上所有内容都是 8 位字符。另请注意,UTF-8 是 Unicode 字符集的编码,它不是本身的字符集,因此您无法查找 UTF-8 代码点

【讨论】:

猜你喜欢
  • 2021-01-02
  • 1970-01-01
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多