PVS-Studio是否了解Unicode字符?
该代码在生产线中的警告瓦特/ return
:PVS-Studio是否了解Unicode字符?
// Checks if the symbol defines two-symbols Unicode sequence bool doubleSymbol(const char c) {
static const char TWO_SYMBOLS_MASK = 0b110;
return (c >> 5) == TWO_SYMBOLS_MASK;
}
// Checks if the symbol defines three-symbols Unicode sequence
bool tripleSymbol(const char c) {
static const char THREE_SYMBOLS_MASK = 0b1110;
return (c >> 4) == THREE_SYMBOLS_MASK;
}
// Checks if the symbol defines four-symbols Unicode sequence
bool quadrupleSymbol(const char c) {
static const char FOUR_SYMBOLS_MASK = 0b11110;
return (c >> 3) == FOUR_SYMBOLS_MASK;
}
PVS说,表达式总是假的(V547),但它们实际上是不:char
可以是Unicode符号的一部分被读取到std::string
! 下面是符号的Unicode表示:1 byte - 0xxx'xxxx - 7 bits
2 bytes - 110x'xxxx 10xx'xxxx - 11 bits
3 bytes - 1110'xxxx 10xx'xxxx 10xx'xxxx - 16 bits
4 bytes - 1111'0xxx 10xx'xxxx 10xx'xxxx 10xx'xxxx - 21 bits
下面的代码计数在Unicode文本符号数:
size_t symbolCount = 0; std::string s;
while (getline(std::cin, s)) {
for (size_t i = 0; i < s.size(); ++i) {
const char c = s[i];
++symbolCount;
if (doubleSymbol(c)) {
i += 1;
} else if (tripleSymbol(c)) {
i += 2;
} else if (quadrupleSymbol(c)) {
i += 3;
}
}
}
std::cout << symbolCount << "\n";
对于Hello!
输入输出是6
和Привет, мир!
是12
—这是对的!
我错了还是不知道PVS知道些什么? ;)
回答:
PVS-Studio分析器知道有符号和无符号字符类型。无论是否使用签名/无符号都取决于编译密钥,并且PVS-Studio分析器考虑了这些密钥。
我认为这个代码是编译的,当char是signed char类型的时候。让我们看看它带来的后果。
让我们来看看只在第一种情况:
bool doubleSymbol(const char c) { static const char TWO_SYMBOLS_MASK = 0b110;
return (c >> 5) == TWO_SYMBOLS_MASK;
}
如果变量的值“C”小于或等于01111111,条件永远是假的,因为在换挡期间的最大值即可得到是011.
这意味着我们只关心变量'c'中最高位等于1的情况。由于这个变量是带符号字符类型,所以最高位表示变量存储一个负值。在转换之前,有符号的char变成了一个有符号的int,并且该值继续为负。
现在让我们来看看有什么标准说,关于负数右移:
E1 >> E2的值E1右移E2位的位置。如果E1具有无符号类型或者E1具有带符号类型和非负值,则结果的值是E1/2^E2的商的整数部分。如果E1有签名类型和负值,则结果值是实现定义的。
因此,向左移动一个负数是实现定义的。这意味着最高位填充了零位或零位。两者都是正确的。
PVS-Studio认为最高位填充了1。它有充分的权利去思考,因为有必要选择任何实现。因此,如果变量'c'中的最高位最初等于1,则表达式((c)>> 5)将具有负值。负数不能等于TWO_SYMBOLS_MASK。
事实证明,从PVS-Studio的角度来看,条件总是错误的,并且它正确地发出警告V547。
实际上,编译器的行为可能会有所不同:最高位将填充0,然后所有内容都将正常工作。
在任何情况下,都需要修复代码,因为它涉及编译器的实现定义的行为。
代码可能是固定的,如下所示:
bool doubleSymbol(const unsigned char c) { static const char TWO_SYMBOLS_MASK = 0b110;
return (c >> 5) == TWO_SYMBOLS_MASK;
}
以上是 PVS-Studio是否了解Unicode字符? 的全部内容, 来源链接: utcz.com/qa/257407.html