我正在阅读源代码文件。但我被困在以下一行
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;
}
答案 0 :(得分:4)
isspace
函数和另一个ctype.h
函数期望int
作为参数。从C11标准第7.4 / 1节:
标题声明了几个对字符分类和映射有用的函数。在所有情况下,参数都是
int
,其值应表示为unsigned char
或等于宏EOF
的值。如果参数具有任何其他值,则行为未定义。
这意味着如果您有以下代码:
char ch = 'é'; // same as: char ch = -126; for some code pages
isspace(ch);
然后此调用会导致undefined behaviour。
这样做的理由是该功能可以作为查找表实现:#define isspace(x) space_table[x]
导致未定义的行为当然很糟糕,因此isspace(ch)
是错误的。修复代码的正确方法是:
isspace( (unsigned char)ch );
在使用2的补码算术的机器上,ch & 0xFF
与(unsigned char)ch
完全等效。
在没有使用2的补码的机器上,它会查找错误的值(但不会导致未定义的行为)。
也许你的程序员很高兴地假设他的代码永远不会运行在带有空格的负字符代码的非2补码机器上,他觉得& 0xFF
比演员更美观。
答案 1 :(得分:3)
此操作强制零值剩余零
[OR]
操作 * ch& 0xff 选择前8位和 isspace 验证value是否为空格char。
答案 2 :(得分:2)
使用0xFF
计算AND运算,提取最低字节,假设每字节8位。对于非负值没有效果,但char
也可以签名,在这种情况下,生成的int
无法在unsigned char
中表示;采用最低字节解决了这个问题。
从技术上讲,在表达式ch & 0xFF
中,操作数被提升为int
,这可能会吓到程序员,因为isspace
的参数是int
,但是值应该适合unsigned char
或具有值EOF
,只能用int
来表示。