【问题标题】:understanding c-'0'理解 c-'0'
【发布时间】:2012-06-19 09:57:08
【问题描述】:

我试图测试使用 c-'0' 的 K&R 函数之一。为了清楚地理解,我写了如下两行代码。我的问题是为什么它打印“1”。在这种情况下,“数值”实际上意味着什么。谢谢!

char c = 'a';
printf("%c",c-'0');

【问题讨论】:

  • 需要说明的是,这段代码在实际应用中没有任何意义,也不应该依赖。

标签: c


【解决方案1】:

c - '0' 仅在 c 为数字('0'、'1'、...或'9')时具有明确的特定值。

当c 是'0' 时,'0' - '0' 是0 因为它们是相等的 当c 是'1' 时,'1' - '0' 是1 因为'1' 在任何C 实现选择使用的任何字符集中紧跟'0'。 '2' 和其他数字相同:'9' - '0' 的值为 9。

而且您真的不应该使用 "%c" 格式说明符打印值。

【讨论】:

    【解决方案2】:

    数值是字符的ASCII值。

    'a' 是 97,'0' 是 48。97-48=49。

    49 又是'1' 的值,所以这就是打印的内容。

    【讨论】:

    • 所以本质上,当(ASCII 5 是 53 而 3 是 51 所以数字是 53 - 51 : 2)printf("ASCII for %c is %d so number is %d - %d : %d\n", '5', '5', '5', '3', '5'-'3');
    • 关于“数字是 53 - 51 : 2”的部分我不明白。上述转换仅对'0' 有意义,因为那是“ASCII 数字中加法的中性元素”:我也可以使用'5' - '3' + 3 将'5' 转换为53,但这比只是'5' - '0'。
    • 我的意思是 '5' - '0' = 5 因为 ASCII 值是 53 - 48,这 = 5。因为在 ASCII 中(断言在任何编码中都是正确的),数字有顺序代码,甚至如果它们不是从 0 开始。这是否正确?
    • 所以基本上 '5' - '0' 因为 ASCII 编码值而可以获得 5 的值?
    • @jslvtr 因为它们在 ASCII 表中相隔 5 个位置:'012345',从值 48 开始。如果 0 位于末尾,例如在电话拨号器上,则此技术将不会不行。
    【解决方案3】:

    C 中的字符只不过是一个整数值。它们的值是根据character encoding 定义的。 ASCII 编码非常有名,适用于 OP 发布的问题。因此,'0' 等于 48,'a' 等于 97。通过减去它们,您就得到了 ASCII 表中这些字符之间的差异。

    在这个例子中(相当于你的):

    printf("%c",'a'-'0');
    

    你得到1,因为 97-48 = 49 对应于 ASCII 字符“1”。

    如果您使用的是(注意“%d”而不是“%c”):

    printf("%d",'a'-'0');
    

    那么这将只打印差异(在本例中为 49),而不是与差异关联的 ASCII 字符。

    【讨论】:

    • 不一定是ASCII,只是一些编码
    • @JensGustedt 我在某种程度上简化了它,因为在 OP 的问题的上下文中,我不认为正在使用另一种编码。无论如何,我会更新问题以反映这一点。
    【解决方案4】:

    代码的行为取决于实现。它依赖于字符的编码。

    在我的 Linux 机器上,a 字符以 ASCII(和 UTF8)编码为单字节 97(十进制),即 0x61。同样,0 字符编码为48,即0x30。 'a' - '0' 的区别是 97 - 48 即 49 恰好是字符 1 的编码

    在一些古老的EBCDIC 机器上(例如旧的 IBM 大型机,或在某种兼容模式或操作系统下运行的新主机)编码是不同的。

    UTF8(现在经常使用)存在更多字符(例如,C cedilla ç 用于法语拼写),并且它们通常被编码为一个以上的字节!

    【讨论】:

      【解决方案5】:

      c - '0' 将从 c 中减去 '0'(48) 的字符代码。如果 c 代表一个数字,这将导致对应于 c 的数值(例如 char '3' 为 3)。

      为了得到这个数值,你应该在 printf 中使用格式说明符 %d 而不是 %c。

      从“a”中减去“0”没有多大意义,但它可能对特定任务有一些应用。

      【讨论】:

        【解决方案6】:

        让我们通过使用整数而不是字符来进一步解释这一点。

        char c = 97;
        printf("%d", c - 48); 
        

        这当然会打印 49,但是当我们使用 ASCII 表将其转换为字符时,我们会得到 1。

        char c = 97;
        printf("%c", c-48);
        

        此代码现在打印 1,因为我们在打印时使用 char 数据类型,它将 49 值转换为 ASCII 等效数字 1。

        为了证明这一点,我们可以尝试这样的事情。

        char a = 'a';
        char b = 97;
        if((a == b) && ((a-'0') == (b-48))) { 
              printf("%s", "true");
        }
        

        首先我们看 a 和 b 是否等价,然后我们看 a-'0' 是否与 b-48 等价。由于两者都为真,我们打印为真。

        【讨论】:

          【解决方案7】:

          单引号内的字符,如'0',是一个字符常量。它是一个数字常数,取决于机器的字符集。在 ASCII 字符集中,'a' 等价于 97,'0' 等价于 48。

          97-48 = 49,相当于 ASCII 字符集中的 '1'。最后,它会以 %c 格式打印 '1'。

          【讨论】:

            猜你喜欢
            • 2017-05-02
            • 2020-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-26
            • 1970-01-01
            • 2020-11-21
            • 1970-01-01
            相关资源
            最近更新 更多