C++中的XOR加密,警告“使用二进制位运算符的带符号整数操作数” 我学习C++中的简单XOR加密算法。

C++中的XOR加密,警告“使用二进制位运算符的带符号整数操作数” 我学习C++中的简单XOR加密算法。,c++,encryption,compiler-warnings,xor,C++,Encryption,Compiler Warnings,Xor,下一个代码工作正常: void test(int8_t* data, const int data_length) { const uint8_t key = 123; for (int index = 0; index < data_length; index++) data[index] = data[index] ^ key; } 我得到的数据是有符号的,因此具有int8\t类型 问题是编译器会显示下一个警告: 带二进制位运算符的有符号整数操作数的

下一个代码工作正常:

void test(int8_t* data, const int data_length) {
    const uint8_t key = 123;

    for (int index = 0; index < data_length; index++)
        data[index] = data[index] ^ key;
}
我得到的数据是有符号的,因此具有int8\t类型

问题是编译器会显示下一个警告:

带二进制位运算符的有符号整数操作数的使用“

在执行异或操作时,我可以通过使用uint8_t强制转换数据来发出警告,但我不知道其含义。我做了一些测试,似乎没有问题,但我很困惑,因为数据可能包含有符号的值,所以我不确定通过强制转换它是否会弄乱数据


即使数据可能包含负值,强制转换到uint8\t是否正确?或者我应该忽略警告吗?

编译器发出警告,因为不应该对有符号整数执行按位操作。在C++ C++ 20之前,允许有符号整数的不同表示,也就是说,相同的数可以用不同的机器和编译器上的不同的位模式来表示。这使得对有符号整数进行位操作的结果不可移植。诚然,intN_t总是需要使用表示法,C++20将该要求扩展到所有带符号整数,但仍然不建议在按位操作中使用带符号整数

在您的特定情况下,data[index]和key都被提升为int以执行异或操作。但是,由于data[index]是一个有符号整数,因此它的值会进行符号扩展,而无符号键会进行零扩展。这意味着异或只影响中间int值的低8位,结果可能不适合int8_t范围。当将结果分配给数据[index ]时,可以发生一个符号溢出,在C++ 20之前,它是C++中的UB;自C++20以来,它被定义为截断高位


在这种情况下,正确的做法是将数据视为原始字节数组,而不管这些字节代表什么值。这意味着您应该使用或std::uint8\t来表示输入和输出数据。这样,您将对无符号整数进行操作,并且没有可移植性或潜在的溢出问题。

对于c++20,您应该使用按位复制:

void test(int8_t* data, const int data_length) {
    const uint8_t key = 123;

    for (int index = 0; index < data_length; index++){
        auto const encrypted = std::bit_cast<std::byte>(data[index]) ^ key;
        data[index] = std::bit_cast<int8_t>(encrypted);
    }
}
对于以前的版本,您应该将有符号类型强制转换为相应的无符号类型

void test(int8_t* data, const int data_length) {
    const uint8_t key = 123;

    for (int index = 0; index < data_length; index++){
        auto const encrypted = static_cast<std::byte>(data[index]) ^ key;
        data[index] = static_cast<int8_t>(encrypted);
    }
}

只是出于好奇-你能告诉我们你使用的是哪种编译器吗?我试过使用MSVC和clang cl,但它们不会生成这样的警告。@AdrianMole这完全取决于您的警告级别;如果您将编译器配置为这样做,GCC、clang和MSVC将提供这样的警告IntelliJ@FabianKeßler我在MSVC VS-2019中启用了/Wall所有警告,但未给出任何警告:无论是在编译还是静态分析中。但是,我可以看到应该有一个警告。static_cast之前没有std::。此外,您可能希望将std::qualification与int8_t和其他类型一致使用,或者忽略它。int8_t和uint8_t不在my clang编译器的全局命名空间中。当然,我可以通过使用std::int8\t;并使用std::uint8\u t;。“FabiangKier-Leer-C++”将ST8NT定义为STD命名空间中的其他标准类型。您可以在全局命名空间中从C包含中看到它,其中许多C++实现都在内部使用。不过,该全局名称不是标准名称,是偶然出现的。@API_1024否,std::byte定义为枚举,基础类型为无符号字符。禁止所有数字操作,只允许按位操作。这是表示您正在处理原始数据的一种方式。@API_1024 std::byte不是别名,它是一种单独的类型,与无符号字符大小相同。转换为std::byte不会更改值的位表示形式,但会更改其解释。由于使用XOR只对位表示进行操作,因此结果与我在回答中提到的sans符号/零扩展相同。