函数std::isdigit
是:
int isdigit(int ch);
返回(如果字符是数字字符则为非零值,否则为零。)闻起来函数是从C继承的,但即使这样也无法解释为什么参数类型为int
而不是{{ 1}}同时......
如果ch的值不能表示为,则行为未定义 unsigned char并且不等于EOF。
char
取isdigits
而不是int
有什么技术原因吗?
答案 0 :(得分:4)
原因是允许EOF
作为输入。而EOF
是(来自here):
EOF类型的EOF整数常量表达式和负值
答案 1 :(得分:1)
可接受的答案是正确的,但我认为这个问题值得更多详细说明。
根据您的实现,C ++中的char
是带符号的还是无符号的(而且,它是与signed char
和unsigned char
不同的类型)。
在C长大的地方,char
通常是无符号的,并假定是一个可以表示[0..2 ^ n-1]的 n 位字节。 (是的,有些机器的字节大小不是8位。)实际上,char
被认为与字节几乎没有区别,这就是为什么像memcpy
这样的函数采用char *
而不是而不是像uint8_t *
之类的东西,为什么sizeof char
总是1,为什么CHAR_BITS
没有命名为BYTE_BITS
。
但是作为C ++的基线的C标准仅承诺char
可以在执行字符集中保留任何值。它们可能具有其他价值,但不能保证。源字符集(基本上是7位ASCII减去一些控制字符)需要类似97的值。有一小段时间,执行字符集可能会更小,但实际上几乎从未如此。最终,明确要求char
的大小足以容纳8位字节。
但是范围仍然不确定。如果未签名,则可以依靠[0..255]。但是,从理论上讲,带符号的字符可以使用符号+大小表示形式,该范围为[-127..127]。请注意,只有255个唯一值,而不是256个值([-128..127]),就像您从二进制补码中获得的那样。如果您足够熟练地使用语言,则可以辩称您无法将8位字节的每个可能值存储在char
中,即使这是整个语言及其运行时库设计的基本假设。我认为C ++最终通过实际上要求带符号的char
使用二进制补码来封闭C ++ 17或C ++ 20中的明显漏洞,即使较大的整数类型使用符号+量级。
当需要设计基本输入/输出功能时,他们不得不考虑如何返回值或信号,该信号或信号已经到达文件末尾。决定使用特殊值而不是带外信令机制。但是要使用什么价值? Unix人士通常可以使用[128..255],其他人可以使用[-128 ..- 1]。
但这仅在您处理文本时使用。 Unix / C人们认为文本字符和二进制字节值是同一回事。因此getc()
也用于从二进制文件读取字节。 char
的所有256个可能值(无论其有无签名)都已声明。
K&R C(在第一个ANSI标准之前)不需要功能原型。编译器对参数和返回类型进行了假设。这就是C和C ++具有“默认升级”的原因,即使它们现在不如以前那么重要了。实际上,您不能从函数返回小于int
的任何东西。如果这样做的话,无论如何它只会被转换为int
。
因此,自然的解决方案是让getc()
返回一个int
,其中包含字符值或一个特殊的文件末尾值,被想象为{{1} },-1的宏。
默认的提升不仅使函数不能返回小于EOF
的整数类型,而且还使传递小类型的内容变得困难。因此,int
也是期望字符的函数的自然参数类型。因此,我们最终得到了像int
这样的函数签名。
如果您是Posix粉丝,基本上这就是您所需要的。
对于我们其余的人,还有一个陷阱:如果您的int isdigit(int ch)
已签名,则-1可能表示您的执行字符集中的合法字符。您如何区分它们?
答案是,函数实际上根本不会使用char
值进行交易。他们确实使用char
装扮成unsigned char
的值。
int