I want to initialize this char vector with this ASCII codes:
vector <char> a = { 201, 187, 200, 188, 205, 186 };
and I get this syntax error in all of the 6 characters:
Invalid narrowing convertion from "int" to "char": constant value does not fit in destination type
but when I initialize a single char variable, with the same ASCII codes:
char b = 201;
It works fine.
So I realized that in vectors, for some reason, char type can receive int values until 127. Starting 128 the syntax error appears.
This is different than in normal variables, when char type can receive any int values.
I tried declaring the vector as unsigned char, and the syntax error dissapears.
vector <unsigned char> a = { 201, 187, 200, 188, 205, 186 };
But still,
Why char type vectors cannot receive the same int data as char type variables?
I really would appreciate someone explaining me this behavior.
There are two things going on.
1
The first is the default range of values for the char
type, which is implementation defined. In most major compilers the default is [-128,127]. (And, oddly, this is not the same as signed char
, JSYK!)
Both MSVC and GCC provide options to treat char
as signed or unsigned. You can do that to fix the problem globally.
Better, though, is not to assume char
handles anything outside the range [0,127]. Use signed char
or unsigned char
to be specific.
2
The second is that you are using brace initialization, which requires that literal element values be checked for range fit.
For your examples:
std::vector <char> xs = { 201, 202 }; // compiler error
char x { 201 }; // compiler error
char x = 201; // compiler warning
If you don’t have your compiler’s error level cranked up (and you should) then the compiler will silently ignore that warning and assign the value, even though it is technically invalid.
There is no built-in way to do that, because character literals are in single quotes only, and numbers (without suffixes) are ints. You can add a L, LL, UL, ULL to make a literal long, long long, and unsigned versions, plus some other for floating points, etc., but no such suffix exists for chars.
However, if you have a C++11 or later compiler, you can write your own user-defined literal to help with this:
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 };
}
If this isn't an option or you just don't like it you could always write an ordinary function to do something similar:
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) };
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With