以下函数int
用作第二个参数类型,
memchr(const void *buf, int ch, size_t count);
虽然它用于一种character
类型。为什么定义函数int
用于类型参数char
?这有什么特别的原因吗?
之所以如此,是因为这是一个非常“古老”的标准函数,从 C 语言演化的早期就存在。
旧版本的 C 没有函数原型之类的东西。函数要么未声明,要么使用“未知”参数列表声明,例如
void *memchr(); /* non-prototype declaration */
调用此类函数时,所有参数都会自动进行参数提升,这意味着此类函数永远不会接收到char
or类型的参数值short
。这样的参数总是被调用者隐式提升为 typeint
并且函数本身实际上收到了一个int
. (对于如上所示声明的函数,即没有原型的现代 C 语言,这仍然是正确的。)
当 C 语言最终发展到引入原型函数声明的地步时,重要的是使新声明与标准函数的遗留行为和已编译的遗留库保持一致。
这就是为什么您永远不会在遗留函数声明的参数列表中看到此类类型char
的原因。short
出于同样的原因,您也不会看到float
那里使用的类型。
这也意味着,如果由于某种原因您必须为以 K&R 样式定义的某些现有遗留函数提供原型声明,则必须记住在原型中指定提升的参数类型。例如对于定义为的函数
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!
因为char
、signed char
和unsigned char
是三种不同的类型。在特定的实现中,您不知道char
是签名还是未签名。
除了在罕见的系统中(参见 Keith 的注释),类型int
包含这三种类型可以具有的所有值。
所有处理字符的标准函数都可以。我认为部分原因是历史原因(在某些 C 的预标准版本中,函数不能接受char
orunsigned char
参数,就像 varargs 参数不能具有字符类型一样),部分原因是所有此类函数的一致性。
为了允许 EOF 的可能性,必须使用一些字符处理函数,但不是其中之一。int
memchr
C 从不将小于 int 的参数传递给函数。将函数参数定义为 char 或 short 始终提升为 int,定义 unsigned char 或 unsigned short 参数始终提升为 unsigned int。
如果 unsigned 与 signed char 是问题,他们会使用短(我不记得短是 1 字节长的单个平台)。
当然,使用 int 可以处理 unsigned 与 signed char 的可能性,因为 memchr 只是比较相等性。