【问题标题】:49 + 82 = -190? c++ ceasar shift49 + 82 = -190? c++ 凯撒移位
【发布时间】:2021-08-19 00:53:26
【问题描述】:

我正在研究加密消息的代码。首先,我像这样应用Ceasar shift:

message[i] += offset;

在 i = 40 的情况下,偏移量等于 49,message[40] 等于 82。所以 82 += 49 应该是 131。(我记录了之前和之后的每个值)而不是 131,message[40] 是现在 -190。

这是整个代码:

string encode(vector<string> rotors, string message, int offset)
{
    for (int i = 0; i < message.length(); i++)
    {
        message[i] += offset; // ceasar shift
        while (message[i] > 'Z') message[i] -= 26; // in case the value of the letter is larger than Z go back to the beginning of the alphabet

        for (int j = 0; j < rotors.size(); j++) // the other part of enigma encryption
        {
            message[i] = rotors[j][message[i] - 65];
        }
        offset++; // increase ceasar shift
    }
    return message;
}

rotors 是一个由随机字母组成的向量,消息是一个不超过 50 个字符的字符串,并偏移一个整数用于 ceasar 移位(如果这很重要)。

所以我的问题是: 为什么它在 82 + 49 中得到 -190?这不仅发生在我的 PC 上,也发生在在线编译器上。

编辑:这仅适用于 i = 40 和 offset = 49 的特殊情况。在所有其他情况下(更大或更小),它按预期工作。

如果你想重现这个:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

string encode(vector<string> rotors, string message, int offset) {
    for (int i = 0; i < message.length(); i++) {
        message[i] += offset;
        while (message[i] > 'Z') message[i] -= 26;
        for (int j = 0; j < rotors.size(); j++) {
            message[i] = rotors[j][message[i] - 65];
        }
        offset++;
    }
    return message;
}

int main()
{
    string message;
    int pseudoRandomNumber;
    vector<string> rotors;
    cin >> pseudoRandomNumber; cin.ignore();

    for (int i = 0; i < 3; i++) {
        string rotor;
        getline(cin, rotor);
        rotors.push_back(rotor);
    }
    getline(cin, message);

    message = decode(rotors, message, pseudoRandomNumber);

    cout << message << endl;
}

复制这个并将其作为输入:

9
BDFHJLCPRTXVZNYEIWGAKMUSQO
AJDKSIRUXBLHWTMCQGZNPYFVOE
EKMFLGDQVZNTOWYHXUSPAIBRCJ
EVERYONEISWELCOMEHEREEVERYONEISWELCOMEHERE

【问题讨论】:

  • “特殊情况”表示您有内存损坏/未定义行为/nasal demons。您能否展示一个minimal reproducible example,其他人都可以完全如图所示剪切/粘贴、编译、运行和重现您的结果?
  • 有符号算术溢出,导致未定义行为。如果普通 char 有符号或无符号,则定义它的实现。在你的情况下,它似乎是一个签名类型。
  • std::string 使用 char 元素。 char 没有附加明确的signedunsigned 将是 有符号或无符号,具体取决于编译器实现。在您的情况下,char 已明确签名,这意味着它的有效范围为-128..127,而131 超出该范围,因此您遇到整数溢出。
  • 请注意,即使您使所有字符都明确无符号(包括字符串中的字符),如果这是您的目标,您仍然会遇到结果可能无法打印的问题。
  • message[40] -190 还是 -125(存储为 8 位二进制补码有符号数时为 82 + 49),其中 -190 来自 -125 - 65(提升后message[i] 在减法之前从 char 到 int)?

标签: c++ char variable-assignment calculation


【解决方案1】:

如果char类型表现为signed char类型,那么可以通过以下方式获得可以存储在该类型对象中的最小值和最大值

#include <iostream>
#include <limits>

int main() 
{
    std::cout << static_cast<int>( std::numeric_limits<char>::min() ) << '\n';
    std::cout << static_cast<int>( std::numeric_limits<char>::max() ) << '\n';

    return 0;
}

程序输出是

-128
127

char 类型的对象无法存储值131

如果以十六进制输出值131

#include <iostream>
#include <iomanip>

int main() 
{
    std::cout << std::hex << std::showbase << 131 << '\n';
    
    return 0;
}

你会得到

0x83

二进制看起来像

10000011

正如所见,符号位已设置

10000011`
^

所以这个存储在char类型的对象中的值代表一个负数。

【讨论】:

  • @Deduplicator 是的,对于有符号整数类型。
  • 溢出仅存在于有符号整数类型。就像有问题的char。因此,我想知道它是否改变了,或者为什么没有人提到它。
猜你喜欢
  • 2014-09-28
  • 2012-06-21
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
相关资源
最近更新 更多