char 和 toupper 的结果不明确

问题描述

'ab' 存储在 char 中是如何转换为 24930 的?

ext.kotlin_version = '1.3.50'

GCC 编译器警告:从“int”到“char”的转换溢出将值从“24930”更改为“98”

输出:B

如果可能,请在此处解释 char 如何处理多个字符。

解决方法

来自 C 标准(6.4.4.4 字符常量)

10 整数字符常量的类型为 int。 包含映射到的单个字符的整数字符常量 单字节执行字符是 被解释为整数的映射字符的表示。 包含多个字符(例如'ab')或包含字符或转义序列的整数字符常量的值 不映射到单字节执行字符,是 实现定义。

所以这个字符常量 'ab' 被存储为 int 类型的对象。然后它被分配给类型为 char 的 ab 对象,就像在这个声明中

char c = 'ab';

然后使用 int 类型对象的最低有效字节来初始化对象 c。在您的情况下,字符 'b' 似乎存储在此最低有效字节中并分配给对象 c

,

您的字符存储在右侧的 4 个字节中。 24930 = 0x6162 相当于 0x61 'a' 和 0x62 'b' = 'ab'

98 是您的“b”,六进制为 0x62,十进制为 98,请查看 man ascii。由于溢出,并且您的系统以小端方式工作,因此您的 2 个字符存储在 4 个字节上,如下所示:

0x62 0x61 0x00 0x00

因为应该只将一个字符分配给 c(字符大小等于 1 个字节,最大限制为 256 位),所以它会截断并只保留第一个字节,即您的 'b'。

您可以使用 char c = 'abcd' 轻松测试它会打印 'D'。

,

符合的 char c 包含单个字符...多个字符需要 char *string 并且您需要遍历字符串,例如:

#include <stdio.h>
#include <cype.h>      // Needed for toupper()

int main()
{
    char *mystring = "ab\0";  // Null terminate
    char *mychar   = mystring;

    while ( *mychar != '\0' )
    {
      char c = toupper( *mychar );
      printf( "%c",c );
      mychar++;
    }
    return 0;
}

顺便说一句,toupper() 返回一个 int,因此存在隐式类型转换。