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

回到顶部