bugprone-signed-char-misuse

cert-str34-c 将此检查作为别名重定向到这里。对于 CERT 别名,DiagnoseSignedUnsignedCharComparisons 选项设置为 false

查找可能表明编程错误的 signed char -> 整数转换。 signed char 的基本问题在于,它可能会将非 ASCII 字符存储为负值。这种行为会导致对已编写代码的误解,无论是在显式转换还是隐式转换发生时。

当代码包含显式的 signed char -> 整数转换时,程序员可能期望转换后的值与字符代码匹配([0..255] 中的值),然而,实际值在 [-128..127] 区间内。为了避免这种误解,从 signed char 转换为整数值的最佳方法是先转换为 unsigned char,它将所有字符存储在正的 [0..255] 区间内,这与已知的字符代码相匹配。

在隐式转换的情况下,程序员可能根本没有意识到发生了转换,并且 char 值被用作整数。有一些用例,这种不知情会导致功能上不完善的代码。例如,应避免在 C++ 代码中检查 signed charunsigned char 变量的相等性。在此比较期间,这两个变量将转换为具有不同值范围的整数。对于 signed char,非 ASCII 字符存储在 [-128..-1] 区间内,而相同的字符在 unsigned char 中存储在 [128..255] 区间内。

默认情况下,普通 char 是作为 signed char 处理,因此会被此检查捕获,这取决于实际平台。要更改默认行为,可以使用 -funsigned-char-fsigned-char 编译选项。

目前,此检查会在以下情况下发出警告: - signed char 被赋值给一个整数变量 - signed charunsigned char 使用相等/不相等运算符进行比较 - signed char 在数组下标中被转换为整数

另请参阅:STR34-C. 在转换为更大的整数大小之前将字符强制转换为 unsigned char

CERT 描述中一个很好的例子是 char 变量用于从可能包含非 ASCII 字符的文件中读取数据。问题出现在代码将 -1 整数值用作 EOF 时,而 255 字符代码也在 char 类型的二进制补码形式中存储为 -1。请参见下面此代码的简单示例。此代码不仅在到达文件末尾时停止,而且在获得代码为 255 的字符时也会停止。

#define EOF (-1)

int read(void) {
  char CChar;
  int IChar = EOF;

  if (readChar(CChar)) {
    IChar = CChar;
  }
  return IChar;
}

修复上述代码的正确方法是先将 char 变量转换为 unsigned char 值。

#define EOF (-1)

int read(void) {
  char CChar;
  int IChar = EOF;

  if (readChar(CChar)) {
    IChar = static_cast<unsigned char>(CChar);
  }
  return IChar;
}

另一个用例是检查两个具有不同符号的 char 变量的相等性。在非 ASCII 值范围内,signed charunsigned char 之间的比较始终返回 false

bool compare(signed char SChar, unsigned char USChar) {
  if (SChar == USChar)
    return true;
  return false;
}

修复这种比较的最简单方法是将其中一个参数强制转换为相同类型。

bool compare(signed char SChar, unsigned char USChar) {
  if (static_cast<unsigned char>(SChar) == USChar)
    return true;
  return false;
}
CharTypdefsToIgnore

用分号分隔的 typedef 名称列表。在此列表中,我们可以列出 charsigned char 的 typedef,这些 typedef 将被检查忽略。当 typedef 引入一个整数别名(如 sal_Int8int8_t)时,这很有用。在这种情况下,人工误解不是问题。

DiagnoseSignedUnsignedCharComparisons

当设置为 true 时,检查将在 signed char/unsigned char 比较上发出警告,否则会忽略这些比较。默认情况下,此选项设置为 true