这个函数究竟是如何将 char 转换为 int 的示例?

How exactly is this function an example of a char to int conversion?

Kernighan 和 Ritchie 的 The C Programming Language 一书,第二版在第 43 页上关于 Type Conversions 的章节中指出:

Another example of char to int conversion is the function lower, which maps a single character to lower case for the ASCII character set. If the character is not an upper case letter, lower returns returns it unchanged.

/* lower: convert c to lower case; ASCII only */
int lower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

它没有在文本中明确提及,所以我想确保我理解正确:当您使用 char 类型的变量调用 lower 函数时会发生转换,不是吗?特别是表达式

c >= 'A'

与从 intchar 的转换无关,因为像 'A' 这样的字符常量 从一开始就在内部作为 int 处理,不是吗?编辑:或者对于本书涵盖的 ANSI C,这是否不同(例如,字符常量被视为 char)?

字符常量的类型如您所料,为 int,因此您认为此函数中没有对 int 的提升是正确的。

如果将 char 类型的变量传递给此函数,则可能会发生任何提升,这很可能是文本所指的内容。

字符常量的类型在当前C17 standard(第6.4.4.4p10节)中都是int

An integer character constant has type int

并且在 C89 / ANSI C standard(语义下的第 3.1.3.4 节)中:

An integer character constant has type int

后者是K&R Second Edition所指的。

K&R C 很旧。真的老了K&R C 的许多细节在最新的标准 C 中不再适用。

在标准的最新 C11 中,您发布的函数中没有转换 to/from char

/* lower: convert c to lower case; ASCII only */
int lower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

该函数接受 int 个参数作为 int c,并且根据 6.4.4.4 Character constants of the C standard,字符文字的类型为 int

因此,C11 下发布的整个 lower 函数完全处理 int 值。

转换(如果有的话)可以在调用函数时完成:

char upperA = 'A`;

// this will implicitly promote the upperA char
// value to an int value
char lowerA = lower( upperA );

请注意,这是 C 和 C++ 之间的差异之一。在 C++ 中,字符字面量是 char 类型,而不是 int.

How exactly is this function an example of a char to int conversion?

/* lower: convert c to lower case; ASCII only */
int lower(int c) {
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

这不是 charint 转换的示例 - 作者在技术上不正确。


文本继续讨论 tolower(c) 作为 lower() 的替代方案,因为它 "works" 正确,即使 [A -Z] 没有像 EBCDIC 那样连续编码].

没有讨论的是 tolower() 函数和其他函数 (is...()) 仅针对 unsigned char 范围内的 int 值和 EOF. C11 §7.4 1. 其他值调用 未定义的行为 (UB)。

正是这种要求使得这些标准 C 库函数在概念上 charint 的转换仅作为(大约)[=12 中的值=] 指定范围,结果为 int.


现在查看确实发生 char 转换的代码 .

void my_strtolower1(char *s) {
  while (*s) {
    *s = lower(*s);  // conversion `char` to `int` and `int` to `char`.
    s++;
  }
} 

void my_strtolower2(char *s) {
  while (*s) {
    *s = tolower(*s); // conversion `char` to `int` and `int` to `char`.
    s++;
  }
} 

void my_strtolower3(char *s) {
  while (*s) {
    // conversion `char` to `unsigned char` to `int` and `int` to `char`.
    *s = tolower((unsigned char) *s); 
    s++;
  }
} 

my_strtolower1() 定义明确,但在 [A-Z,a-z] 不连续的稀有机器上功能不正确。

my_strtolower2() 预期的功能,除了 *s < 0(而非 EOF)时技术上未定义的行为。

my_strtolower3() *s < 0.

时没有 UB 的预期功能