ANSI C:为啥字符函数接受 int 参数而不是 char 参数?

Posted

技术标签:

【中文标题】ANSI C:为啥字符函数接受 int 参数而不是 char 参数?【英文标题】:ANSI C: Why character functions accept int argument instead of char argument?ANSI C:为什么字符函数接受 int 参数而不是 char 参数? 【发布时间】:2012-02-16 07:39:34 【问题描述】:

为什么字符函数接受 int 参数而不是 char 参数?

<ctype.h>

int isalnum(int c); 
int isalpha(int c); 
int iscntrl(int c); 
int isdigit(int c); 
int isgraph(int c); 
int islower(int c); 
int isprint(int c); 
int ispunct(int c); 
int isspace(int c); 
int isupper(int c); 
int isxdigit(int c); 
int tolower(int c); 
int toupper(int c); 

【问题讨论】:

我怀疑答案类似于给定的here。在 C 中,字符文字的类型为 int @Cody:这两个决定可能是相关的,因为在 C 中对字符进行“计算”的正确数据类型是 int。但是与这些函数的参数具有相同类型的文字并不像看起来那么简单。你可以写isalnum('a'),但不能保证你能写isalnum(CHAR_MIN),或者在你的实现中对应于CHAR_MIN的任何字符文字,因为它可能是负数。为了与这些函数正确匹配,字符文字确实需要类型 unsigned,但将它们转换为 char 可能会很糟糕。 【参考方案1】:

字符和整数在 C 中紧密结合。

当您从输入流中接收到一个字符时,它必须能够表示每个字符加上文件结束符号。

这意味着 char 类型不够大,因此他们使用更宽的类型。

C99 基本原理文档指出:

由于这些函数通常主要用作宏,因此它们的域仅限于可以用 unsigned char 表示的小的正整数,加上 EOF 的值。 EOF 传统上是 -1,但可以是任何负整数,因此可以与任何有效字符代码区分开来。因此,这些宏可以通过使用参数作为一个小属性数组的索引来有效地实现。

标准本身是这样说的:

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

【讨论】:

“下一个最大的类型”实际上是short。但是,当这些被发明出来时,short 将被提升为 int,就像 char 一样。 @JerryCoffin 你什么意思?每当在表达式中使用时,所有 short 仍会提升为 int。 @AmirSaniyan: while ((mychar = tolower(getchar()) != EOF) /* do stuff */ 从技术上讲,非 ascii 值返回未定义的值,但什么时候有“这种行为是未定义的”曾经阻止过任何人依赖它吗? @Jerry: 更重要的是,当这些被发明时,short 在许多地方与char 的大小相同。尽管标准没有明确要求它,int 几乎在任何地方都大于char。如果它们的大小相同,则实现者将需要一个特殊的“保留”负值,它不是执行字符集中的代码点,并且永远不能从任何类型的输入(包括例如二进制文件流)中读取,并将其用作EOF。我不确定这是否合法,因为这意味着char 的值无法写入文件并读回。 @SteveJessop:哪个编译器的 char 和 short 大小相同?我很确定 AT&T 编译器和 Whitesmiths 都没有。我记得有很多非常早期的编译器(例如 BDS C)根本没有 short,但没有一个与 char 大小相同。【参考方案2】:

最初发明 C 时,没有对函数参数进行编译时检查。如果一个名为foo(bar,boz)barboz 的类型为int,编译器会将两个int 值压入堆栈,调用foo,并希望得到两个@987654327 @ 值。由于在计算表达式时小于int 的整数类型被提升为int,所以在原型发明之前编写的C 函数不能传递任何更小的整数类型。

【讨论】:

【参考方案3】:

除了正常的字符值之外,它们还必须接受 EOF。它们也早于函数原型的发明。那时,没有办法将char 传递给函数——它总是首先被提升为int

【讨论】:

【参考方案4】:

是的,它可以容纳始终为非字符值的 EOF,尽管 EOF 的确切值可能因不同的系统而异,但它永远不会与任何字符代码相同。

【讨论】:

以上是关于ANSI C:为啥字符函数接受 int 参数而不是 char 参数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Hex() 函数返回一个字符串而不是一个 int hex?

在 Julia 中,为啥 @printf 是宏而不是函数?

strcmp函数怎么用的?

如果标准 golang big.Int 函数接受两个参数并返回一个值,为啥它会使用接收器?

为啥 C 字符文字是整数而不是字符?

C++ 下UNICODE编程与多字符集编程有啥区别?