isspace(ch & 0xff)的含义是什么?

3
我正在阅读一个源代码文件,但我卡在了以下这一行。
while (isspace (* bp & 0xff))
    ++ bp;

我知道基本思路是去掉空格。但是我不知道下面这个函数中的0xff到底是在做什么。

static enum tokens scan (const char * buf)
{
    static const char * bp;

if (buf)
    bp = buf;       /* new input line */

while (isspace (* bp & 0xff))
    ++ bp;

if (isdigit (* bp & 0xff) || * bp == '.')
{
    errno = 0;
    token = NUMBER, number = strtod (bp, (char **) & bp);
    if (errno == ERANGE)
        error ("bad value: %s", strerror (errno));
}
else
token = * bp ? * bp ++ : 0;

    return token;
}

bp 的类型是什么? - edmz
3
请展示周围的代码,特别是bp的定义和内容。 - orlp
作者拥有多年的编程经验。起初他写的是isspace(*bp),但后来他改变了它。因此,我在这里寻找一个有意义的原因。 - Begginer
3个回答

4
isspace('a');

You may actually encounter undefined behavior because the parameter passed to isspace is a character constant and not an int. To avoid this, you should use:

isspace((unsigned char)'a');

This ensures that the argument passed to isspace is indeed an int with a value representable by an unsigned char.

char ch = 'é';   // same as: char ch = -126; for some code pages

isspace(ch);

那么这个调用会导致未定义行为

之所以这样做是为了使函数可以实现为查找表:#define isspace(x) space_table[x]

当然,导致未定义行为是不好的,因此isspace(ch)是错误的。修正代码的正确方法是:

isspace( (unsigned char)ch );

在使用2的补码算术的机器上,ch & 0xFF恰好等同于(unsigned char)ch
在不使用2的补码的机器上,它将查找错误的值(但不会导致未定义的行为)。
也许你的程序员很乐意假设他的代码永远不会在具有负字符代码的非2的补码机器上运行,并且他认为& 0xFF比转换更美观。

我不想相信任何编译器供应商会以一种无法用于“char c”中的任何内容的方式编写isspace(和任何其他类似的函数)... 你能给我展示这样的编译器的例子吗? - PiotrNycz
显然过去曾经有这样的编译器,否则 ANSI C 的作者们不会觉得有必要以这种方式编写标准来支持这样的编译器。 - M.M
(ch & 0xFF) 对于有符号字符没有任何作用。-1 & 0xFF 仍然是 -1。 - John Hammond
@M.M 你在作弊 ;) %d 是错误的参数。使用 %hhd 看看它是否正常工作。 - John Hammond
@LarsFriedrich ch&0xFF 的类型是 int,所以 %d 是正确的说明符。您似乎忘记了整数提升。如果仍然不确定,请尝试 sizeof(ch&0xFF) - M.M
显示剩余8条评论

3
这个操作是将值左侧强制填充零。
[或者]
操作*ch & 0xff选择前8位,并且isspace验证该值是否为空格字符。

2
或者,取*bp的8个最低有效位。 - Iharob Al Asimi
谢谢,我想我找到了答案。由于isspace()中char被提升为int,并且带有关注行的作者希望确保它始终是ansi-c char。非常感谢。 - Begginer

2

使用0xFF进行AND操作提取最低字节,假设每个字节有8位。对于非负值没有影响,但char也可以是有符号的,在这种情况下,结果为int不能用unsigned char表示;取最低字节可以解决此问题。

从技术上讲,在表达式ch & 0xFF中,操作数被提升为int,这可能会使程序员感到害怕,因为isspace的参数是一个int,但该值应适合于unsigned char或具有值EOF,只能用int来表示。


尝试一下:char ch = -2; printf("%d\n", ch & 0xFF); - M.M
@M.M 谢谢,好观点,我没有考虑到可能存在负值。 - edmz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接