为啥函数 `memchr()` 使用 `int` 作为 `char` 类型的参数?

Posted

技术标签:

【中文标题】为啥函数 `memchr()` 使用 `int` 作为 `char` 类型的参数?【英文标题】:Why does the function `memchr()` use `int` for the argument of `char` type?为什么函数 `memchr()` 使用 `int` 作为 `char` 类型的参数? 【发布时间】:2013-04-03 21:39:52 【问题描述】:

以下函数使用int作为第二个参数类型,

memchr(const void *buf, int ch, size_t count);

虽然它用于character 类型。为什么函数定义为使用int 作为char 类型的参数?这有什么特别的原因吗?

【问题讨论】:

您可能还想阅读这基本上是相同的问题。 ***.com/questions/5919735/… 【参考方案1】:

之所以如此,是因为这是一个非常“古老”的标准函数,从 C 语言演化的早期就存在。

旧版本的 C 没有函数原型之类的东西。函数要么未声明,要么使用“未知”参数列表声明,例如

void *memchr(); /* non-prototype declaration */

在调用此类函数时,所有参数都会自动进行参数提升,这意味着此类函数从未收到charshort 类型的参数值。这样的参数总是被调用者隐式提升为类型int,而函数本身实际上收到了int。 (在现代 C 中,对于如上所示声明的函数,即没有原型,这仍然是正确的。)

当 C 语言最终发展到引入 prototype 函数声明的地步时,将新声明与标准函数的旧行为和已编译的旧库保持一致非常重要。

这就是为什么您永远不会在遗留函数声明的参数列表中看到charshort 这样的类型的原因。出于同样的原因,您也不会在此处看到类型 float


这也意味着,如果出于某种原因您必须为某些以 K&R 样式定义的现有遗留函数提供原型声明,您必须记住在原型中指定 promoted 参数类型。例如。对于定义为的函数

int some_KandR_function(a, b, c)
char a;
short b;
float c;


正确的原型原型声明实际上是

int some_KandR_function(int a, int b, double c);

但不是

int some_KandR_function(char a, short b, float c); // <- Incorrect!

【讨论】:

【参考方案2】:

因为charsigned charunsigned char 是三种不同的类型。在特定的实现中,您不知道char 是签名的还是未签名的。

除了在稀有系统中(参见 Keith 的注释),int 类型包含这三种类型可以具有的所有值。

【讨论】:

在大多数系统上。如果sizeof (int) == 1(暗示CHAR_BIT &gt;= 16),那么int 可能无法保存unsigned char 类型的所有值。这样的系统很少见。 @pmg 这就是我用 EOF 完成“char、signed char 和 unsigned char”的原因。【参考方案3】:

所有处理字符的标准函数都可以。我认为部分原因是历史原因(在某些 C 的预标准版本中,函数不能采用 charunsigned char 参数,就像 varargs 参数不能具有字符类型一样),部分原因是为了保持所有的一致性这样的功能。

有一些字符处理函数可以使用 int 以允许 EOF 的可能性,但 memchr 不是其中之一。

【讨论】:

您真的是指“EOL”吗?【参考方案4】:

C 从不将小于 int 的参数传递给函数。将函数参数定义为 char 或 short 始终提升为 int,定义 unsigned char 或 unsigned short 参数始终提升为 unsigned int。 如果 unsigned 与 signed char 是问题,他们会使用短(我不记得短是 1 字节长的单个平台)。 当然,使用 int 可以处理 unsigned 与 signed char 的可能性,因为 memchr 只是比较相等性。

【讨论】:

以上是关于为啥函数 `memchr()` 使用 `int` 作为 `char` 类型的参数?的主要内容,如果未能解决你的问题,请参考以下文章

C 标准库 - string.h之memchr使用

可以用memchr实现吗?

size_t——为什么支持size_t,何时使用size_t?

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

为啥指向函数的“const”指针不能在常量表达式中使用?

为啥使用 static_cast<int>(x) 而不是 (int)x?