【问题标题】:ASCII TABLE - negative value [duplicate]ASCII TABLE - 负值 [重复]
【发布时间】:2012-10-21 02:28:43
【问题描述】:

可能重复:
Negative ASCII value

int main() {
    char b = 8-'3';
    printf("%c\n",b);

    return 0;
}

我运行这个程序,我得到一个看起来像问号 (?) 的符号。

我的问题是为什么它打印那个而不打印任何内容,因为据我所知,ASCII 表中 b 的值是负 43,这是不存在的。

顺便说一句,当我编译这段代码时:

int main() {
    char b = -16;
    printf("%c\n",b);

    return 0; 
}

我什么也得不到。

【问题讨论】:

标签: c char ascii


【解决方案1】:

没有“负 ASCII”值这样的东西。 ASCII 为 0 到 127 的值定义字符和控制代码。

大多数系统不使用纯 ASCII。他们使用其他一些字符集。对于 0 到 127 的值,几乎所有其他字符集都与 ASCII 匹配,但它们为更高的值定义了额外的字符和控制代码。

在某些 C 和 C++ 实现中,char 对应于一个带符号的字符,它的取值范围为 -127 到 +127(大多数情况下为 -128 到 +127)。在其他实现中,char 是一个从 0 到 255 的无符号值。

如果您有一个带负值的签名char 并尝试打印它,库会将其视为unsigned char(例如,-1 变为 255),它将打印平台字符中的任何字符set 对应于该值。如果没有分配给特定值的字符,库可能会选择显示一些默认占位符字符,例如问号或框。

【讨论】:

    【解决方案2】:

    这是C 2011 standard 中指定的行为

    7.21.6.1 fprintf 函数

    ...
    8 转换说明符及其含义是:
    ...
    c 如果不存在 l 长度修饰符,则 int 参数将转换为 unsigned char,然后写入生成的字符。

    如果存在 l 长度修饰符,则 wint_t 参数将被转换为 一个没有精度的ls 转换规范和一个指向的参数 到wchar_t 的二元素数组的初始元素,第一个元素 包含wint_t 参数到lc 转换规范和 第二个空宽字符。

    -43 正在转换为无符号值 (213),因此它正在打印扩展的 ASCII 字符。

    【讨论】:

    • 并且由于char 的签名是实现定义的,我们不知道对于这个特定的编译器它是签名还是未签名。它是“某物”,然后在传递给 printf 时转换为 unsigned char。
    【解决方案3】:

    您可以参考ASCII table。并且所有数字都应映射到 (256+(value))%256 (这是处理overflows 的方式)。您应该能够找到为哪个数字打印哪个符号。

    【讨论】:

    • ASCII 只定义从 0 到 127 的值。还有(许多)其他字符集为高于该范围的值定义附加字符,并与较低范围的 ASCII 定义匹配。这些其他字符集有时称为“扩展 ASCII”,但“扩展 ASCII”没有单一定义。 128-255 之间的值的映射取决于正在使用的字符集(或代码页)。
    • 我共享的链接确实包含扩展 ASCII 表的“版本”。我提出的决定哪个角色的逻辑对我来说很好。
    【解决方案4】:

    %c 格式将始终打印一个字符,因此大概它只需要您的char 的位并将其视为无符号值,最终设置为最高位。您的终端可能会将这些字符显示为空白或带问号的占位符,但我的终端显示 Õ 和 ð...

    如果您想在值为负数时不打印任何内容,则需要检查它(并使用更大的数据类型,例如int,以便您可以将非字符值与所有可能的字符一起拟合, 或signed char,如果你想确保你得到一个有符号的类型;一个普通的char 可以是有符号的或无符号的)。

    【讨论】:

      【解决方案5】:

      字符在打印时在内部被解释为“无符号”。因此,它将是 255 - 16 = 第 239 个字符。顺序为 239 的 ascii 值打印在屏幕控制台上。同样 -43 是 212 订单。

      【讨论】:

      • (256 - 16) 和 (256 - 43)。你的基础差了一个。
      • 256 = 0? IIRC 编号是从 00 -> FF = 00 到 255?但你可以在这里。我离开了1
      • 在 8 位域中,256 0,因为当修剪所有位超过 [0..7] 时 0x100 = 0x00。
      【解决方案6】:

      这是因为 -16 与十六进制 0xf0 相同,后者与 240 相同。在我的字符集 (ISO 8859-1) 中,该字符是 LATIN SMALL LETTER ETH'ð'

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-27
        • 1970-01-01
        • 2011-03-20
        • 1970-01-01
        • 2012-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多