【问题标题】:Initialize vector <char> with int values用 int 值初始化向量 <char>
【发布时间】:2017-12-21 23:32:58
【问题描述】:

我想用这个 ASCII 码初始化这个字符向量:

vector <char> a = { 201, 187, 200, 188, 205, 186 };

我在所有 6 个字符中都得到了这个语法错误:

从“int”到“char”的无效缩小转换:常量值不适合目标类型

但是当我使用相同的 ASCII 码初始化单个 char 变量时:

char b = 201;

效果很好。

所以我意识到,在向量中,由于某种原因,char 类型可以接收 int 值,直到 127。从 128 开始出现语法错误。

这与普通变量不同,char 类型可以接收任何 int 值。

我尝试将向量声明为无符号字符,语法错误消失了。

vector <unsigned char> a = { 201, 187, 200, 188, 205, 186 };

不过,

为什么 char 类型向量不能接收与 char 类型变量相同的 int 数据?

我真的很感谢有人向我解释这种行为。

【问题讨论】:

  • 如果是常规字符,则不能超过 126。它是否适用于无符号字符?
  • 那么为什么“char b=201”有效?
  • 它给你一个溢出编译器错误
  • 转到你的编译器,在你做char b=201之后,你应该在下面添加std::cout &lt;&lt; "Char c equals 201? " &lt;&lt; std::boolalpha &lt;&lt; (c == 201) &lt;&lt; std::endl;,然后看看你得到的输出
  • 此外,下次编译代码时,请确保使用-pedantic 标志。使用该标志会警告您此溢出,您认为这是正常的

标签: c++ vector char int narrowing


【解决方案1】:

发生了两件事。

1
第一个是char 类型的默认值范围,实现定义。在大多数主要编译器中,默认值为 [-128,127]。 (而且,奇怪的是,这signed char,JSYK!)

MSVC 和 GCC 都提供了将 char 视为已签名或未签名的选项。您可以这样做以全局解决问题。

不过,最好不要假设 char 处理 [0,127] 范围之外的任何内容。具体使用signed charunsigned char

2
第二个是您使用的是brace initialization,这需要检查文字元素值是否适合范围。

你的例子:

std::vector <char> xs = { 201, 202 };  // compiler error

char x { 201 };  // compiler error

char x = 201;  // compiler warning

如果您没有提高编译器的错误级别(并且应该),那么编译器会默默地忽略该警告并分配值,即使它在技术上是无效的。

【讨论】:

  • 谢谢!!这真的很有帮助。最后一个疑问。我知道,如果编译器在不适合的情况下分配该值,我将丢失数据。为什么我仍然得到我期望的角色? (ASCII 码 =201)在本例中。
  • @WalterS.Escobedo 编译器将环绕在chars 范围内(这不能保证,但几乎所有编译器在从int 转换时都会这样做)。因此,它分配值-55。这与正 201 的底层字节相同,当您将其写出时,它会以相同的方式发送到屏幕。
  • 感谢 Daniel H。这真的很有帮助!
【解决方案2】:

没有内置的方法可以做到这一点,因为字符文字只有单引号,而数字(没有后缀)是整数。您可以添加 L、LL、UL、ULL 来制作文字 long、long long 和无符号版本,以及其他一些用于浮点等的版本,但不存在用于 chars 的此类后缀。

但是,如果您有 C++11 或更高版本的编译器,您可以编写自己的用户定义文字来帮助解决此问题:

constexpr char operator "" _c(unsigned long long arg) noexcept
{
    return static_cast<char>(arg);
}

int f()
{
  std::vector <char> a = { 201_c, 187_c, 200_c, 188_c, 205_c, 186_c };
}

如果这不是一个选项,或者你只是不喜欢它,你总是可以编写一个普通的函数来做类似的事情:

constexpr char c(int arg) noexcept
{
    return static_cast<char>(arg);
}

int f()
{
  std::vector <char> a = { c(201), c(187), c(200), c(188), c(205), c(186) };
}

【讨论】:

  • 您刚刚定义了_c 运算符吗?酷
  • @smac89 不过没必要
  • 感谢您的回复,但我对 char 类型的行为更感兴趣。为什么char b=201;有效,为什么vector &lt;char&gt; b ={201}; 无效?
  • 这不是真的。可以将 int 转换为 char 而无需新的运算符或函数(正如您可以编写函数的事实所见)。这也不能避免转换超出范围的问题;您的行为仍然是实现定义的。最后,它没有回答这个问题:它没有说明 为什么 char b = 201 有效,但 char b{201}std::vector&lt;char&gt; v = { 201 } 无效。
  • @WalterS.Escobedo 这是因为 {201},一个朴素的数字文字的类型为“int”。当你把它放在一个字符中时,你就改变了类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
相关资源
最近更新 更多