【问题标题】:Strings of unsigned chars无符号字符串
【发布时间】:2013-12-16 04:20:12
【问题描述】:

这里有一个有趣的。我正在编写一个 AES 加密算法,并设法让它进行准确的加密。当我尝试将结果写入文件时,麻烦就来了。我得到的文件输出不正确。十六进制值会被破坏,而且通常是荒谬的(即使按照加密标准)。

我通过在将加密输出发送到文件之前对其进行采样进行了一些调试。我发现我在某个地方出现了某种溢出。当正确的十六进制值应该是 9e 时,我会得到 ffffff9e。它只会对高于 7F 的十六进制值执行此操作,即未正确处理“扩展”字符集中的字符。这在我的项目早期也发生在我身上,然后问题是使用 char[][] 容器而不是 unsigned char[][] 容器。

我的代码使用字符串在用户界面和 AES 加密类之间传递加密数据。我猜 std::strings 不支持扩展字符集。所以我的问题是:有没有办法实例化一个无符号字符串,还是我必须找到一种方法来替换我对字符串的所有使用?

【问题讨论】:

  • 这种情况经常发生在 MS-Windows 上。他们char被认为是签名的(即使在mingwin和其他移植到MS-Windows的Unix开发工具中)。在Linux下,它类似于unsigned char(但仍然是一个单独的类型。)

标签: c++ string encryption


【解决方案1】:

std::string 实际上只是一个 typedef,类似于:

namespace std { 
   typedef basic_string<char> string;
}

unsigned char 创建一个变体相当容易:

typedef basic_string<unsigned char> ustring;

但是,您必须更改代码以使用 ustring(或您喜欢的任何名称)而不是 std::string

根据您编写代码的方式,可能虽然不需要编辑所有代码。特别是,如果你有类似的东西:

namespace crypto { 
   using std::string;

   class AES { 
      string data;
      // ..
    };
}

您可以通过仅更改 using 声明来更改字符串类型:

namespace unsigned_types { 
    typedef std::basic_string<unsigned char> string;
}

// ...

namespace crypto {
    using unsigned_types::string;

    class AES {
        string data;
    };
}

还要注意,模板的不同实例化是完全独立的类型,即使它们实例化的类型是相关的,所以您可以在 charunsigned char 之间隐式转换的事实并不意味着您' 将在 basic_string&lt;char&gt;basic_string&lt;unsigned char&gt; 之间获得匹配的隐式转换。

【讨论】:

    【解决方案2】:

    std::string 只不过是std::basic_string&lt;&gt; 模板的特化,所以你可以简单地做一个

    typedef std::basic_string<unsigned char> ustring;
    

    得到你想要的。


    请注意,C/C++ 标准没有定义 char 是有符号还是无符号类型,因此任何将 char 直接转换为更大类型的程序都会调用实现定义的行为。

    【讨论】:

    • 如何从 [unsigned] char 转换为更大的有符号类型给 UB?较大的类型需要至少大一点,在这种情况下,任何 unsigned char 值都可以在较大的类型中表示而无需修改(在这种情况下,这正是发生的情况)。
    • @JerryCoffin 对不起,我在这里搞砸了 UB 和实现定义的行为。根据标准,转换为不能表示转换值的有符号整数类型是实现定义的(我认为它是 UB)。我相应地修正了答案。
    • 重点不在于 UB 与 IB。这是因为任何可以用一种大小的无符号表示的值总是可以用更大大小的有符号表示。
    • @JerryCoffin 啊,现在我明白你的意思了。但我想,我上次编辑时已经更正了,不是吗?在任何情况下,如果我将值 0x80char 转换为 uint_16,我可能会得到 0x00800xff80,具体取决于编译器/平台。
    • 是的,我同意你现在所拥有的。
    【解决方案3】:

    首先将您的价值投给unsigned char

    char input = 250;                                    // just an example
    
    unsigned int n = static_cast<unsigned char>(input);  // NOT: "unsigned int n = input;"
    //               ^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    问题是您的char 恰好是已签名,因此它的值不是您想要的“字节值”——您必须转换为unsigned char 才能得到它.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-01
      • 2021-05-28
      • 1970-01-01
      相关资源
      最近更新 更多