用 int 值初始化向量 <char>
Initialize vector <char> with int values
我想用这个 ASCII 代码初始化这个 char 向量:
vector <char> a = { 201, 187, 200, 188, 205, 186 };
我在所有 6 个字符中都遇到了这个语法错误:
Invalid narrowing convertion from "int" to "char": constant value does not fit in destination type
但是当我使用相同的 ASCII 代码初始化单个 char 变量时:
char b = 201;
它工作正常。
所以我意识到在向量中,出于某种原因,char 类型可以接收 int 值直到 127。从 128 开始出现语法错误。
这与普通变量不同,当 char 类型可以接收任何 int 值时。
我尝试将向量声明为 unsigned char,语法错误消失了。
vector <unsigned char> a = { 201, 187, 200, 188, 205, 186 };
但是,
为什么 char 类型向量不能接收与 char 类型变量相同的 int 数据?
我真的很感激有人向我解释这种行为。
没有内置的方法可以做到这一点,因为字符文字仅用单引号引起来,而数字(没有后缀)是整数。您可以添加 L、LL、UL、ULL 来制作文字 long、long long 和无符号版本,再加上其他一些用于浮点等,但字符不存在此类后缀。
但是,如果您有 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) };
}
有两件事正在发生。
1
第一个是 char
类型的默认值范围,即 实现定义 。在大多数主要编译器中,默认值为 [-128,127]。 (奇怪的是,这 与 signed char
不同,,JSYK!)
MSVC 和 GCC 都提供了将 char
视为已签名或未签名的选项。您可以这样做以在全球范围内解决问题。
不过,最好不要假设 char
处理范围 [0,127] 之外的任何内容。使用 signed char
或 unsigned char
来具体说明。
2
第二个是您正在使用 brace initialization,这需要检查文字元素值是否适合范围。
举个例子:
std::vector <char> xs = { 201, 202 }; // compiler error
char x { 201 }; // compiler error
char x = 201; // compiler warning
如果您没有提高编译器的错误级别(您应该),那么编译器将默默地忽略该警告并分配该值,即使它在技术上是无效的。
我想用这个 ASCII 代码初始化这个 char 向量:
vector <char> a = { 201, 187, 200, 188, 205, 186 };
我在所有 6 个字符中都遇到了这个语法错误:
Invalid narrowing convertion from "int" to "char": constant value does not fit in destination type
但是当我使用相同的 ASCII 代码初始化单个 char 变量时:
char b = 201;
它工作正常。
所以我意识到在向量中,出于某种原因,char 类型可以接收 int 值直到 127。从 128 开始出现语法错误。
这与普通变量不同,当 char 类型可以接收任何 int 值时。
我尝试将向量声明为 unsigned char,语法错误消失了。
vector <unsigned char> a = { 201, 187, 200, 188, 205, 186 };
但是,
为什么 char 类型向量不能接收与 char 类型变量相同的 int 数据?
我真的很感激有人向我解释这种行为。
没有内置的方法可以做到这一点,因为字符文字仅用单引号引起来,而数字(没有后缀)是整数。您可以添加 L、LL、UL、ULL 来制作文字 long、long long 和无符号版本,再加上其他一些用于浮点等,但字符不存在此类后缀。
但是,如果您有 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) };
}
有两件事正在发生。
1
第一个是 char
类型的默认值范围,即 实现定义 。在大多数主要编译器中,默认值为 [-128,127]。 (奇怪的是,这 与 signed char
不同,,JSYK!)
MSVC 和 GCC 都提供了将 char
视为已签名或未签名的选项。您可以这样做以在全球范围内解决问题。
不过,最好不要假设 char
处理范围 [0,127] 之外的任何内容。使用 signed char
或 unsigned char
来具体说明。
2
第二个是您正在使用 brace initialization,这需要检查文字元素值是否适合范围。
举个例子:
std::vector <char> xs = { 201, 202 }; // compiler error
char x { 201 }; // compiler error
char x = 201; // compiler warning
如果您没有提高编译器的错误级别(您应该),那么编译器将默默地忽略该警告并分配该值,即使它在技术上是无效的。