I have a buffer like this:
vector<unsigned char> buf
How can I cast it to char*?
If I do:
(char *)buf
I get this error:
/home/richard/Desktop/richard/client/src/main.cc:102: error: invalid cast from type ‘std::vector<unsigned char, std::allocator<unsigned char> >’ to type ‘char*’
For those wondering why I am trying to do this. I need to pass the buffer to this function:
n_sent = sendto(sk,(char *)buf,(int)size,0,(struct sockaddr*) &server,sizeof(server));
And it only accepts char*.
reinterpret_cast<char*> (&buf[0]);
The vector guarantees that its elements occupy contiguous memory. So the "data" you seek is actually the address of the first element (beware of vector <bool>, this trick will fail with it). Also, why isn't your buffer vector<char> so that you don't need to reinterpret_cast?
Update for C++11
reinterpret_cast<char*>(buf.data());
reinterpret_cast<char*>(buf.data());
Try
(char *)(&buf[0])
or another, more C++ cast. But also tell us what you're using this for. It may be a bad idea.
It's very unlikely that you want to cast vector<unsigned char> to unsigned char *, but you can get a a valid pointer like this:
vector<unsigned char> v;
unsigned char *p = &*v.begin();
That strange expression will give you the pointer to the start of the internal allocated array created by the vector. If you modify the vector at all it may no longer be valid.
The reason for the redundant looking &* is that the * is really operator * on the iterator returned by v.begin(). That returns a reference to the first char of the array which you can then take the address of with &.
Related
I tried to convert QByteArray to std::vector<unsigned char> using this code:
unsigned char* buffer = (unsigned char*)byteArrayBuffer.constData();
std::vector<unsigned char>::size_type size = strlen((const char*)buffer);
std::vector<unsigned char> bufferToCompress(buffer, buffer + size);
but, assuming that byteArrayBuffer is a QByteArray filled with data, I think it doesn't work well on line unsigned char* buffer = (unsigned char*)byteArrayBuffer.constData(); because byteArrayBuffer.size() returns a different value than bufferToCompress.size().
How can I get it working?
I'm not familiar with Qt, but surely you just want
std::vector<unsigned char> bufferToCompress(
byteArrayBuffer.begin(), byteArrayBuffer.end());
Note: strlen is not particularly useful in C++; it tells you the length of a C-style null-terminated string (by searching memory until it either finds either finds a zero-valued byte, or falls off the end of accessible memory and crashes), but can't tell you the size of an array, which is what you'd need here. Also, using evil C-style casts to force invalid code to compile is never a good idea.
As I see here http://qt-project.org/doc/qt-4.8/qbytearray.html QByteArray does not have begin/end methods. But have data/length. Result code may be looks like this:
const unsigned char* begin = reinterpret_cast<unsigned char*>(byteArrayBuffer.data());
const unsigned char* end = begin + byteArrayBuffer.length();
std::vector<unsigned char> bufferToCompress( begin, end );
I can across reinterpret casts, and most of the time it was brought up, a warning was given, so I am wondering if there are other alternatives (or clean implementations of reinterpret cast of course)
You don't say what warning was given or what the problem was, but casting to char* with reinterpret_cast should work without warnings:
unsigned char *a;
const char *b = reinterpret_cast<char*>(a);
It depends on what you're trying to do.
If you just want to access the contents as char, then a simple
static_cast or using the value in a context where a char is expected
will do the trick.
If you need to pass the buffer to a function expecting a char const*,
a reinterpret_cast is about the only solution.
If you want a string, using the pointers into the buffer will be fine:
std::string
bufferToString( unsigned char const* buffer, size_t length )
{
return std::string( buffer, buffer + length );
}
or you can copy into an existing string:
myString.assign( buffer, buffer + length );
myString.append( buffer, buffer + length );
// etc.
Any string function (or algorithm, like std::copy) which takes two
iterators can be used. All that is required is that dereferencing the
iterator result in a type which converts implicitly to char, which is
the case of unsigned char.
(You cannot use the string functions which take a buffer address and a
length, as these are not templates, and require the buffer address to
have type char const*. And while unsigned char converts implicitly
to char, unsigned char* requires a reinterpret_cast to convert it
to char*.)
When I try the following, I get an error:
unsigned char * data = "00000000"; //error: cannot convert const char to unsigned char
Is there a special way to do this which I'm missing?
Update
For the sake of brevity, I'll explain what I'm trying to achieve:
I'd like to create a StringBuffer in C++ which uses unsigned values for raw binary data. It seems that an unsigned char is the best way to accomplish this. If there is a better method?
std::vector<unsigned char> data(8, '0');
Or, if the data is not uniform:
auto & arr = "abcdefg";
std::vector<unsigned char> data(arr, arr + sizeof(arr) - 1);
Or, so you can assign directly from a literal:
std::basic_string<unsigned char> data = (const unsigned char *)"abcdefg";
Yes, do this:
const char *data = "00000000";
A string literal is an array of char, not unsigned char.
If you need to pass this to a function that takes const unsigned char *, well, you'll need to cast it:
foo(static_cast<const unsigned char *>(data));
You have many ways. One is to write:
const unsigned char *data = (const unsigned char *)"00000000";
Another, which is more recommended is to declare data as it should be:
const char *data = "00000000";
And when you pass it to your function:
myFunc((const unsigned char *)data);
Note that, in general a string of unsigned char is unusual. An array of unsigned chars is more common, but you wouldn't initialize it with a string ("00000000")
Response to your update
If you want raw binary data, first let me tell you that instead of unsigned char, you are better off using bigger containers, such as long int or long long. This is because when you perform operations on the binary literal (which is an array), your operations are cut by 4 or 8, which is a speed boost.
Second, if you want your class to represent binary values, don't initialize it with a string, but with individual values. In your case would be:
unsigned char data[] = {0x30, 0x30, 0x30, 0x30, /* etc */}
Note that I assume you are storing binary as binary! That is, you get 8 bits in an unsigned char. If you, on the other hand, mean binary as in string of 0s and 1s, which is not really a good idea, but either way, you don't really need unsigned char and just char is sufficient.
unsigned char data[] = "00000000";
This will copy "00000000" into an unsigned char[] buffer, which also means that the buffer won't be read-only like a string literal.
The reason why the way you're doing it won't work is because your pointing data to a (signed) string literal (char[]), so data has to be of type char*. You can't do that without explicitly casting "00000000", such as: (unsigned char*)"00000000".
Note that string literals aren't explicitly of type constchar[], however if you don't treat them as such and try and modify them, you will cause undefined behaviour - a lot of the times being an access violation error.
You're trying to assign string value to pointer to unsigned char. You cannot do that. If you have pointer, you can assign only memory address or NULL to that.
Use const char instead.
Your target variable is a pointer to an unsigned char. "00000000" is a string literal. It's type is const char[9]. You have two type mismatches here. One is that unsigned char and char are different types. The lack of a const qualifier is also a big problem.
You can do this:
unsigned char * data = (unsigned char *)"00000000";
But this is something you should not do. Ever. Casting away the constness of a string literal will get you in big trouble some day.
The following is a little better, but strictly speaking it is still unspecified behavior (maybe undefined behavior; I don't want to chase down which it is in the standard):
const unsigned char * data = (const unsigned char *)"00000000";
Here you are preserving the constness but you are changing the pointer type from char* to unsigned char*.
#Holland -
unsigned char * data = "00000000";
One very important point I'm not sure we're making clear: the string "00000000\0" (9 bytes, including delimiter) might be in READ-ONLY MEMORY (depending on your platform).
In other words, if you defined your variable ("data") this way, and you passed it to a function that might try to CHANGE "data" ... then you could get an ACCESS VIOLATION.
The solution is:
1) declare as "const char *" (as the others have already said)
... and ...
2) TREAT it as "const char *" (do NOT modify its contents, or pass it to a function that might modify its contents).
sqlite3_column_text returns a const unsigned char*, how do I convert this to a std::string? I've tried std::string(), but I get an error.
Code:
temp_doc.uuid = std::string(sqlite3_column_text(this->stmts.read_documents, 0));
Error:
1>.\storage_manager.cpp(109) : error C2440: '<function-style-cast>' : cannot convert from 'const unsigned char *' to 'std::string'
1> No constructor could take the source type, or constructor overload resolution was ambiguous
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?
On the off-chance you actually want a string of unsigned characters, you could create your own type:
typedef std::basic_string <unsigned char> ustring;
You should then be able to say things like:
ustring s = sqlite3_column_text(this->stmts.read_documents, 0);
The reason people typically use an (unsigned char *) type is to indicate that the data is binary and not plain ASCII text. I know libxml does this, and from the looks of it, sqlite is doing the same thing.
The data you're getting back from the sqlite call is probably UTF-8 encoded Unicode text. While a reinterpret_cast may appear to work, if someone ever stores text in the field that is not plain ASCII, your program probably won't be well-behaved.
The std::string class isn't designed with Unicode in mind, so if you ask for the length() of a string, you'll get the number of bytes, which, in UTF-8, is not necessarily the same thing as the number of characters.
Short answer: the simple cast may work, if you're certain the data is just ASCII. If it can be any UTF-8 data, then you need to handle encoding/decoding in a smarter way.
I'm not familiar with sqlite3_column_text, but one thing you may want to do is when you call the std:string constructor, you'll want to cast to (const char*). I believe that it should have a constructor for that type.
However, it is odd that this sqlite function is return an unsigned char*, is it returning a Pascal string (first char is the length of the string)? If so, then you'll have to create the std::string with the bytes and the length.
if temp_doc.uuid is a std::string try :
temp_doc.uuid = static_cast<const char*>(sqlite3_column_text(this->stmts.read_documents, 0));
try:
temp_doc.uuid = std::string(reinterpret_cast<const char*>(sqlite3_column_text(this->stmts.read_documents, 0)));
You can't construct a std::string from const unsigned char* -- you have to cast it to const char* first:
temp_doc.uuid = std::string( reinterpret_cast< const char* >(
sqlite3_column_text(this->stmts.read_documents, 0) ) );
I'm no expert but this example here seems much simpler:
string name = (const char*) (sqlite3_column_text(res, 0));
An old but important question, if you have to preserve the full information in the unsigned char sequence. In my opinion that is with reinterpret_cast not the case. I found an interesting solution under converting string to vector
which I modified to
basic_string<unsigned char> temp = sqlite3_column_text(stmt, 0);
string firstItem( temp.begin(), temp.end() );
Since I am programming for gtkmm, you can realize the conversion into a Glib::ustring with
basic_string<unsigned char> temp = sqlite3_column_text(stmt, 0);
Glib::ustring firstItem = string( temp.begin(), temp.end() );
I have a (void*) buffer that I need to convert to std::vector<unsigned char> before I can pass it on. Unfortunately, my C++ casting skills a little weak. Any suggestions?
You will need the length of the buffer. Once you do, we can do this:
unsigned char *charBuf = (unsigned char*)voidBuf;
/* create a vector by copying out the contents of charBuf */
std::vector<unsigned char> v(charBuf, charBuf + len);
Okay, the comment got me started on why I did not use reinterpret_cast:
In C++, the C-style cast is a convenience function -- it asks the compiler to choose the safest and most portable form of conversion over the set of available cast operators.
The reinterpret_cast is implementation defined and should always be the last thing on your mind (and used when you are necessarily doing a non-portable thing knowingly).
The conversion between (unsigned doesn't change the type) char * and void * is portable (you could actually use static_cast if you are really picky).
The problem with the C-style cast is: the added flexibility can cause heartaches when the pointer type changes.
Note: I agree with the general convention of not casting as much as possible. However, without any source provided, this is the best I could do.
You can't simply cast a void* to a std::vector<unsigned char> because the memory layout of the latter includes other objects, such as the size and the number of bytes currently allocated.
Assuming the buffer is pointed to by buf and its length is n:
vector<unsigned char> vuc(static_cast<char*>(buf), static_cast<char*>(buf) + n);
will create a copy of the buffer that you can safely use.
[EDIT: Added static_cast<char*>, which is needed for pointer arithmetic.]
The only time this would be legitimate is if you had already created a vector, and simply wanted to get it back.
void SomeFunc(void* input);
main() {
std::vector< unsigned char > v;
SomeFunc((void*) &v);
}
SomeFunc(void* input) {
// Now, you could cast that void* into a vector
std::vector< unsigned char >* v_ = (vector<unsigned char>*)input
}
I haven't actually tried to see if this will run, but that's the spirit of it. That said, if you are making this from scratch, you are definitely doing it wrong. This is really bad. The only time this could be even remotely understandable is if you are forced to implement the already defined "SomeFunc()".
using std::vector class for an already allocated buffer is not a solution. A std::vector object manages the memory and deallocates it at destruction time.
A complicated solution might be to write your own allocator, that uses an already allocated buffer, but you have to be very careful on several scenarios, like vector resizing, etc.
If you have that void* buffer bound through some C API functions, then you can forget about conversion to std::vector.
If you need only a copy of that buffer, it can be done like this:
std::vector< unsigned char> cpy(
(unsigned char*)buffer, (unsigned char*)buffer + bufferSize);
where bufferSize is the size in chars of the copied buffer.