string size after converting const unsigned char[] to std::string
case 1: input is not explicitly null-terminated, and likely those global arrays are placed in memory sequentially, so you get at least 48 bytes without zeros, finally it finds some zero 8 bytes ahead, so total is 56.
case 2: here you give it explicit length, and that's the correct way to do things in case of null terminator absence.
case 3: similar to case 1, but just starts from array 3, and takes same extra 8 bytes until null terminator found somewhere.
Solutions: either add null terminators (zero byte) or use variant with explicit length specification.
Way to get unsigned char into a std::string without reinterpret_cast?
Use the iterator constructor:
std::string my_std_string(my_txt, my_txt + my_txt_len);
This is assuming that you want the unsigned chars to be converted to char. If you want them to be reinterpreted, then you should use reinterpret_cast
. That would be perfectly clean, since what you say is exactly what is done.
In your example, though, it doesn't make any difference, because all of the values in your array are within the range 0
to CHAR_MAX
. So it's guaranteed that those values are represented the same way in char
as they are in unsigned char
, and hence that reinterpreting them is the same as converting them. If you had values greater then CHAR_MAX
then implementations are allowed to treat them differently.
C++ conversion from unsigned char to std::string
To append a character you have to use the following overloaded method append
basic_string& append(size_type n, charT c);
For example
stroutput.append(1, characters[0]);
stroutput.append(1, characters[1]);
Otherwise use method push_back
or the operator +=
. For example
stroutput += characters[0];
stroutput += characters[1];
If you want to append the whole array or its part then you can write
stroutput.append( reinterpret_cast<char *>( characters ), sizeof( characters ) );
stroutput.append( reinterpret_cast<char *>( characters ), n );
where n is the number of characters of the array to append.
const unsigned char * to std::string
You could try:
temp_doc.uuid = std::string(reinterpret_cast<const char*>(
sqlite3_column_text(this->stmts.read_documents, 0)
));
While std::string
could have a constructor that takes const unsigned char*
, apparently it does not.
Why not, then? You could have a look at this somewhat related question: Why do C++ streams use char instead of unsigned char?
std::cout not properly printing std::string created by reinterpret_cast of unsigned char array
Change
std::cout << my_std_string << std::endl; // Bad stuff happens :S
to
for( std::size_t i = 0; i < my_txt_len ; i++ )
{
std::cout << std::hex << static_cast<unsigned>(my_std_string[i]) << " " ;
}
std::cout << std::endl;
A std::string
is a representation of a string, not purely an array of bytes. Therefore, passing it to std::cout
will show a string. Your printf
is printing individual values of your unsigned char
array. The stl equivalent of this is an std::vector<unsigned char>
.
You need to add the static_cast<unsigned>()
. Otherwise std::cout
will print each unsigned char
value as a char
ascii character. The output will be R _ s h ~ ) 3 t t s r U
. You have to prevent this conversion by implicitly telling it.
error: cannot convert 'const unsigned char (*)[7]' to 'const unsigned char (*)[]' in initialization
TL;DR:
Replace
Sequence s1 = {&ic_1tc_1};
with
const uint8_t *s1[] = {ic_1tc_1};
Explanation:
Let's start with simple things.
When you omit the array size in a definition, the size is deduced:
int x[] = {1,2,3};
Here, the type of x
is int[3]
.
Note that the type is not int[]
. Types representing arrays of unknown bound are incomplete types, and no objects of such types can be created.
Above works even with typedef
s:
typedef int array[];
array x = {1,2,3};
Note that the type of x
is not array
, since it's int[3]
rather than int[]
.
Even though objects of incomplete types can't be created, you can create pointers to such types.
For example:
int (*ptr)[];
This declaration has the same effect as:
typedef int array[];
array *ptr;
The only thing this pointer could point to is int[]
, but since objects of such type can't be created, pointers to arrays of unknown bound aren't used often.
(Although I can imagine some peculiar use cases. You could declare an array to have an unknown bound and specify a size when defining it elsewhere. You could then form a pointer to the array using the declaration, and the type of such pointer will be T(*)[]
.)
You can't assign an address of int[N]
to such a pointer, since formally int[]
and int[N]
are different types.
typedef int array[];
array x = {1,2,3};
array *ptr = &x; // Error, can't convert `int(*)[3]` to `int(*)[]`.
This is exactly what you're trying to do in your code.
One possible solution is to use the correct type for the pointer:
typedef int array[];
array x = {1,2,3};
int (*ptr)[3] = &x;
But since you said you need to have an array of pointers to arrays of various sizes, that is not an option.
Another possible solution is to cast the pointer, but that doesn't look convenient (and I'm not 100% sure using the resulting pointer is well-defined).
You probably should just store pointers to first elements of your arrays:
typedef int array[];
array x = {1,2,3};
int *ptr = x;
In your code it would look like so:
const Testcase ic_1tc_1 = {0x00, 0x10, 0x01, 0x61, 0x00, 0x30, 0x07};
const uint8_t *s1[] = {ic_1tc_1};
How to convert string to const unsigned char* without using reinterpret_cast (modern approach)
What is the correct way to change a string or const char* to const unsigned char*?
The correct way is to use reinterpret_cast.
If you want to avoid reinterpret_cast, then you must avoid the pointer conversion entirely, which is only possible by solving the XY-problem. Some options:
- You could use
std::basic_string<unsigned char>
in the first place. - If you only need an iterator to unsigned char and not necessarily a pointer, then you could use
std::ranges::views::transform
which uses static cast for each element. - You could change the function that expects
unsigned char*
to acceptchar*
instead.
If you cannot change the type of input
and do need a unsigned char*
and you still must avoid reinterpret cast, then you could create the std::basic_string<unsigned char>
from the input using the transform view. But this has potential overhead, so consider whether avoiding reinterpret_cast is worth it.
Best way to join and store a char string with a wchar_t string in c++
std::vector<unsigned char> Buffer;
for (size_t i = 0; i < sizeof(section1); ++i)
Buffer.push_back((unsigned char) section1[i]);
for (size_t i = 0; i < section2.size(); ++i) {
unsigned short u = (unsigned short) section2[i];
Buffer.push_back((unsigned char) (u >> 8));
Buffer.push_back((unsigned char) (u & 0xFF));
}
for (size_t i = 0; i < sizeof(section3); ++i)
Buffer.push_back((unsigned char) section31[i]);
You can also use memcpy for section 1 and 3, and if you make assumptions about endianness for section2 as well. The above loops should be easy to read and understand though.
When done, you simply write Buffer.size() bytes starting from &Buffer[0]
Related Topics
Print MACro Values Without Knowing the Amount of MACros
Convert a Number to a String with Specified Length in C++
C++11 Lambdas: Member Variable Capture Gotcha
Getting Useful Gcov Results for Header-Only Libraries
Instantiate Class with or Without Parentheses
Making Qlabel Behave Like a Hyperlink
How to Use Clang++ with -Std=C++11 -Weverything -Werror
Understanding Gcc 5's _Glibcxx_Use_Cxx11_Abi or the New Abi
How to Write an Adl-Enabled Trailing Return Type, or Noexcept Specification
Noexcept, Stack Unwinding and Performance
How to Choose Heap Allocation VS. Stack Allocation in C++
Why Does Visual Studio Not Perform Return Value Optimization (Rvo) in This Case
Node Packages Not Building on Windows 8.1 - Missing Microsoft.Cpp.Default.Props
What Could Go Wrong If Copy-List-Initialization Allowed Explicit Constructors