为什么putchar、toupper、tolower等使用int而不是char?

为什么putchar、toupper、tolower等使用int而不是char?,c,putchar,tolower,toupper,C,Putchar,Tolower,Toupper,在C语言中,字符串是字符数组(char*),字符通常存储在char中。我注意到libC中的一些函数将作为参数整数而不是字符 例如,让我们以使用int的函数toupper()和tolower()为例。手册页上说: 如果c不是无符号字符值或EOF,则 函数未定义 我的猜测是,使用int,touper和tolower可以处理无符号字符和EOF。但事实上,EOF实际上是一个可以用char存储的值(关于它的值有什么规则吗?),既然这些函数不会将EOF转换成其他东西,我想知道为什么toupper不简单地将c

在C语言中,字符串是字符数组(
char*
),字符通常存储在
char
中。我注意到libC中的一些函数将作为参数整数而不是字符

例如,让我们以使用
int
的函数
toupper()
tolower()
为例。手册页上说:

如果c不是无符号字符值或EOF,则 函数未定义

我的猜测是,使用
int
touper
tolower
可以处理
无符号字符
EOF
。但事实上,
EOF
实际上是一个可以用
char
存储的值(关于它的值有什么规则吗?),既然这些函数不会将
EOF
转换成其他东西,我想知道为什么
toupper
不简单地将char作为参数

在任何情况下,为什么我们需要接受不是字符的东西(比如EOF)?有人能给我提供一个相关的用例吗

这与
fputc
putchar
类似,它们也接受一个
int
,该值被转换为
无符号字符

我正在寻找这一选择的确切动机。我想确信,我不想回答有一天是否有人问我。

如果c不是无符号字符值或EOF,这些函数的行为是未定义的

但是在C语言中,
EOF
是一个负的
int
,一些平台(hi-ARM!)具有
char
无符号char
相同

标题
声明了几个用于分类和映射的函数 人物。在所有情况下,参数都是int,其值应为 可表示为无符号字符,或应等于 宏EOF。如果参数有任何其他值,则行为为 未定义

C117.21.1

EOF

它扩展为整型常量表达式,类型为int和 负值

C标准明确规定,EOF始终是一个带有负值的整数。此外,默认
char
类型的签名是实现定义的,因此它可能没有签名,并且不能存储负值:

C116.2.5

如果基本执行字符集的成员存储在字符中 对象,其值保证为非负。如果有的话 字符存储在char对象中,结果值为 实施已定义,但应在以下值范围内: 可以在该类型中表示


BITD编码方法包括:

/* example */
int GetDecimal() {
  int sum = 0;
  int ch;
  while (isdigit(ch = getchar())) { /* isdigit(EOF) return 0 */
    sum *= 10;
    sum += ch - '0';
    }
  ungetc(ch, stdin);  /* If c is EOF, operation fails and the input stream is unchanged. */
  return sum;
}
具有EOF值的
ch
可用于各种功能,如
isalpha()
tolower()

这种风格导致了
putchar(EOF)
的问题,我怀疑这与
putchar(255)
的问题相同

由于各种原因,现在不鼓励这种方法。首选以下各种型号

int GetDecimal() {
  int ch;
  while (((ch = getchar()) != EOF)) && isdigit(ch)) {
    ...
  }
  ...
}

我不知道
EOF
必须符合
char
的任何规则,我可以向您保证
char
不保证签名,这使得您关于使用
char
而不是
无符号char
的讨论似乎是错误的。你的意思是整个过程都是
signed char
。你看过这些函数的实现吗。我认为
int
参数是为了优化,因为它的字节大小非常适合处理器寄存器的大小。反过来,一个字节
char
变量必须在幕后转换为
int
,此操作需要一些处理器时间来处理。请阅读以下内容:关于使用示例,我有+1您的答案。但正如你所说,这是不鼓励的,那么为什么
isdigit
应该接受不是字符的东西呢?@Maxime我确信
isdigit()
接受
-1
是历史性的。从概念上讲,不难将EOF看作另一个
char
isthis…()
函数通常使用256字节数组实现,使257字节数组也接受EOF(-1)是很简单的。因为它很简单,并且使得代码更紧凑,所以当紧凑的代码具有更高的价值时,它是一个很好的扩展。现在,随着代码维护值的不断增加,这个习惯用法已经失去了人们的青睐。是的,但在重要的地方,C标准说“unsigned char或EOF”。我的一个问题是:为什么一个将字母转换为另一个字母的函数应该接受非字母的内容?(包括EOF)另一个答案回答了您的问题(为什么像
tolower()
这样的函数需要接受非字母的东西,例如
EOF
)——因为在像
tolower(ch=getchar())
这样的惯用情况下,
ch
,它是
int
,很可能是
EOF
,因此,
tolower
可以接受
EOF