【问题标题】:Print decimal value of a char打印字符的十进制值
【发布时间】:2017-08-02 13:12:24
【问题描述】:

打印字符十进制值的程序:

#include<stdio.h>

int main(void){

  char ch = 'AB';
  printf("ch is %d\n",ch);

}

为什么打印第二个字符的十进制值,为什么不是第一个字符的十进制值?

输出:ch is 66

【问题讨论】:

  • 'AB' 不是合法的字符常量。
  • 这实际上编译没有错误吗? 'AB' 不是字符,它是 两个 字符。
  • @Useless 是的,它正在编译没有错误。
  • @stark: 多字符常量合法的;该标准描述并说明了它们。它只是说值是实现定义的。

标签: c


【解决方案1】:

因为'AB' 是一个多字符常量,其值是由实现定义的,所以无论是66 与否,原则上和实践中都是“不可预测”,尽管不同的可预测性并不相同实现。

通常,您只在单引号中间使用单个字符。如果你使用多个字符,

  1. 编译器应该对此发出警告。
  2. 如果对应的int 的值是“不可预测”,因为它是实现定义的。当然,给定一个实现,我们希望多字符常量始终具有相同的值。

如果你使用过gcc,那么according to this source

编译器一次计算一个字符的多字符字符常量,将前一个值左移每个目标字符的位数,然后在截断到宽度的新字符的位模式中进行或运算的目标人物。最后的位模式被赋予 int 类型,因此是有符号的,无论单个字符是否有符号。如果常量中的字符多于目标 int 中的字符数,编译器会发出警告,并忽略多余的前导字符。

例如,对于具有 8 位字符的目标,'ab' 将被解释为“(int) ((unsigned char) 'a' * 256 + (unsigned char) 'b')”,而'\234a' 将被解释为“(int) ((unsigned char) '\234' * 256 + (unsigned char) 'a')

【讨论】:

  • 所以不是说只取第二个字符?
  • 完全没有,虽然我们不知道实现的细节。但肯定不是因为它忽略了第一个字符而只取了第二个字符。
  • 感谢您的帮助。
  • 不同意“定义的实现,无论是否为 66 都不是真正可预测的。”。这是可以预见的。简单回顾一下平台的实现。
  • @grek40 perthis answer,“必须为阅读编译器文档的用户提供足够的信息,以准确预测特定情况下会发生什么。”因此,在可能和实际的领域中,随机行为将不符合实际标准。
【解决方案2】:
char ch = 'AB';
printf("ch is %d\n",ch); // Output "ch is 66"

为什么打印第二个字符的十进制值,为什么不是第一个字符的十进制值?


'AB' 是一个int 字符常量。

包含多个字符(例如,'ab')或包含不映射到单字节执行字符的字符或转义序列的整数字符常量的值是实现定义的。 C11 §6.4.4.4 10

示例:您的输出可能不同。

printf("ch is %d\n",'AB'); // prints "ch is 16706"

16706 与 0x4142 的值相同,后者是 ASCII AB 的串联值。可以打印出ch is 16961 (0x4241) 或ch is 1111556096 (0x42410000) 或其他文件。这是实现定义的行为

16706 分配给char 要么是实现定义的行为,要么是明确定义的——取决于char已签名 还是未签名。一个常见的 ID 结果是分配低字节,或0x42。 `

printf("ch is %d\n", ch); // prints "ch is 66"

char 范围之外的值分配给char 可能会引发警告。

// Example warning
// warning: overflow in implicit constant conversion [-Woverflow]
char ch1 = 'AB';
char ch2 = 16706;

此外,鉴于此类辅音的实现定义性质,以下内容也可能会发出警告:

// Example warning
// warning: multi-character character constant [-Wmultichar]
char ch1 = 'AB';

多字符字符常量的使用仅限于少数选择情况。如此之少,它更有可能是一个很好用的编码错误。

【讨论】:

    【解决方案3】:

    C11 $6.4.4.4(字符常量):

    一个多字符总是解析为一个int,但确切的值是 “依赖于实施”。也就是说,不同的编译器可能会解析 相同的多字符到不同的整数。这是一个便携 问题,这也是不鼓励使用多字符的原因之一。

    这意味着int ch = 'AB';对于int类型是可以的。但是,如果它被声明为char类型,第二个字节将不会被保留。

    所以用

    char ch = 'A';
    

    而不是

    char ch = 'AB';
    

    并为char 类型使用%c 格式说明符。

    printf("ch is %c\n",ch);
    

    【讨论】:

    • "%d"printf("ch is %d\n",ch); 一起使用并没有什么不妥
    • "并为char 类型使用%c 格式说明符。"不,OP 想要一个十进制值。
    【解决方案4】:

    伊哈罗布是对的。 'AB' 是一个多字符结果是不可预测的。如果您打算保留'AB' 这两个字符,我建议将此常量声明为字符串char ab[] = "AB";。字符串的打印可以是printf("ch is %d\n", ab[0]);,以将65 作为输出。

    【讨论】:

    • 这将完整打印字符串,而不是执行 OP 的要求。
    • 你是对的。已更改打印以适合第一个字符的输出。
    • 还是不正确,现在打印第一个元素的地址。
    【解决方案5】:
    1. 首先,这个程序会抛出类似的警告

      4:12: warning: multi-character character constant [-Wmultichar]
      In function 'int main()':
      4:12: warning: overflow in implicit constant conversion [-Woverflow]
      
    2. 如果您知道运算符优先级的概念,将帮助您了解为什么要获得第二个字符(B)的十进制值。在赋值运算符中,优先级从右到左开始。所以在这种情况下,最右边的字符具有更高的优先级并存储到 char ch 中,其余字符被忽略。

      #include<stdio.h>
      
      int main(void){
      
      char ch = 'AB';           // Here B is assigned to 'ch' and A is ignored.
      char ch1 = 'ABCDEFG';     // Here G is assigned to 'ch1'
      
      printf("ch is %d\n",ch);
      printf("ch1 is '%c'\n",ch1);
      
      }
      

    输出:

    ch is 66
    ch1 is 'G'
    

    另一个使用赋值运算符的例子:

        #include<stdio.h>
    
        int main(void){
    
        int a = (2,3,4,5,6);           // Here 6 is assigned to 'a' and remaining values are ignored.
        printf("a is %d\n",a);
    
        }
    

    输出:

    a is 6
    

    请通过以下链接了解运算符优先级。 http://en.cppreference.com/w/c/language/operator_precedence

    【讨论】:

    • 如果我们只有一个操作符,那么操作符的优先级有多高?多字符文字中没有逗号。
    • "所以在这种情况下,最右边的字符具有更高的优先级并存储到 char ch 中,其余字符被忽略。"是不正确的 - 但它肯定是一种思考字符解析和运算符优先级的新颖方式。
    • 但是确切的值是“依赖于实现的”没什么好说的......
    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多