I am trying to compile this library using MSVC10, and this function is giving me headache:
/*! \brief Read bytes from a \c std::istream
\param is The stream to be read.
\param data A pointer to a location to store the bytes.
\param size The number of bytes to be read.
*/
void _read(std::istream &is, unsigned char *data, int size)
{
for (int i=0; i < size ; ++i )
is.get(static_cast<char>(data[i]));
}
error C2664: 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::get(_Elem &)' : cannot convert parameter 1 from 'char' to 'char &'
The original used static_cast, so I try with reinterpret_cast as suggested elsewhere but that fails too:
error C2440: 'reinterpret_cast' : cannot convert from 'unsigned char' to 'char'
This library comes with unix makefiles. What is the best way to resolve this compile error?
Because reinterpret_cast does not work that way, by definition.
In order to perform memory re-interpretation, you have to apply reinterpret_cast to pointers or references. If you want to reinterpret unsigned char data as char data, you actually have to convert to char & type, not to char type.
In your case that would be
is.get(reinterpret_cast<char &>(data[i]));
Or you can go the pointer route and do
is.get(*reinterpret_cast<char *>(&data[i]));
(which is the same thing).
Because you need a char& that is a reference to char but the result of the cast is an r-value, and so not bindable to the reference.
You need something like:
is.get(reinterpret_cast<char&>(data[i]));
But in this particular case you can / should use static_cast<char&>:
is.get(static_cast<char&>(data[i]));
Try this instead:
void _read(std::istream &is, unsigned char *data, int size)
{
for (int i=0; i < size ; ++i )
is.get(reinterpret_cast<char*>(data)[i]);
}
In addition to the other answers which cope with the casting problem:
Why don't you just use istream::read to read size bytes at once? This avoids your hand-crafted for-loop and should be faster.
void _read(std::istream &is, unsigned char *data, int size) {
is.read(reinterpret_cast<char*>(data), size);
}
Related
So i have this function which receives a pointer:
int myfunc( const char *token, unsigned char *plaintext )
I do my stuff and i end up with a char array:
unsigned char my_plaintext[1024];
Now i need to set that pointer (plaintext) to what's in my_plaintext.
I've tried many different ways but i haven't yet figure this one out...
This part is in a cpp file, and i've even tried:
std::string tmpstr( my_plaintext );
But this comes back with:
token_crypto.cpp:131:13: error: invalid conversion from 'char*' to 'unsigned char*' [-fpermissive]
my_plaintext
^~~~~~~~~~~~
And
std::string tmpstr( (char *)my_plaintext );
'�5�B'
this does compiles but the content is all wrong:
EDIT:
The content of my_plaintext is fine:
int myfunc( const char *token, unsigned char *plaintext ) {
unsigned char my_plaintext[1024];
... some processing stuff (specifically gcm_decrypt) to which is pass my_plaintext ...
cout << my_plaintext
// prints: hello:world
but then however i try set the contents of plaintext to whatever is in my_plaintext either fails at compilation or prints some weird characters.
If you know that plaintext already points at an array that is 1024 long (or longer) then you can use memmove():
int myfunc( const char *token, unsigned char *plaintext )
{
unsigned char my_plaintext[1024];
/* ... fill in my_plaintext here ... */
memmove(plaintext, my_plaintext, 1024);
/* ... rest of function ... */
}
Note that the parameters to memmove are destintation and then source rather than the other way round.
It's up to the caller of your function to make sure the pointer they pass in points to at least 1024 bytes.
You can use memcpy() instead in this case, but using memmove() is good practice in general.
The C++ string constructor doesn't take an unsigned char *. See the C++ reference here:
http://www.cplusplus.com/reference/string/string/string/
You need to cast the unsigned char array to a char array. See how to do that here:
How to Convert unsigned char* to std::string in C++?
This is where I call the function..
memcpy(dataHashResult,sha1.operator()(dataBuffer,16),16);
I changed
/// compute SHA1 of a memory block
std::string operator()(const void* data, size_t numBytes);
to
std::string operator()(BYTE* data, size_t numBytes);
the types of buffers are..
unsigned char dataBuffer[64];
unsigned char dataHashResult[64];
Any help would be appreciated ..I'm new to C++..
Thanks.
try this:
memcpy(dataHashResult,sha1.operator()(dataBuffer,16).c_str(),16);
The problem is that memcpy needs a pointer to copy from. Your original code gives it a std::string object. Luckily, std::string has a c_str() function that returns the "C-style" string, i.e. a const char*.
I have an encryption function declared as follows: int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext). This works perfectly and now I call it according to the given snippet.
const char *password = "password";
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
On compiling the C++ code I get an error as:
crest.cc:52:13: error: no matching function for call to 'encrypt'
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
^~~~~~~
./aes.h:10:5: note: candidate function not viable: no known conversion from 'const char *' to 'unsigned char *' for 1st argument
int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext);
What is the correct way to typecast in C++ to get around this error ?
There are several problems with this code, and the only (correct) way to fix them is to ensure that you use the correct data types in the first place.
So, instead of const char *password = "password", use unsigned char password[] = "password"; (of course, this will probably give you trouble with strlen, since it won't like unsigned char) - using sizeof(password)-1 will work in THIS instance, but is ill advised as a general solution, since password may well be not be directly available as an array - not sure quite what you should do as an "ideal" solution, really.
Now, the question can be asked whether it is actually correct to have a non-const input to the function. If you have the source for encrypt, you may want to change the function to encrypt(const unsigned char* keydata, size_t keydata_len, const unsigned char* plaintext, size_t plaintext_len, unsigned char* ciphertext) - still doesn't fix the problem with strlen of unsigned char of course, but it's what I'd expect the prototype to be for a function like this.
An alternative would be to rewrite the encrypt function to make casts to unsigned only internally, and use char * inputs (with const where relevant).
Note that it's NOT valid to cast away constness EXCEPT for cases where you know that the original content is not const (which I think is NOT guaranteed to be the case for std::string::c_str(), but std::string::data() should work)
I was using some class which has a method requiring:
const unsigned char *sData
as parameter.
When I called following:
char dataIn[]="The quick brown fox jumps over the lazy dog";
obj.CRC(dataIn,strlen(dataIn),&checksum); // compute checksum
I got error:
Error 1 error C2664: 'void crcClass::CRC(const unsigned char *,size_t,unsigned int *)' : cannot convert parameter 1 from 'char [44]' to 'const unsigned char *'
So I modified above code like this and it works:
obj.CRC((const unsigned char*)dataIn,strlen(dataIn),&checksum); // compute checksum
Is the modification I did alright?
It's OK, but for "safety" consider using reinterpret_cast<const unsigned char*>(dataIn) instead.
This is safer in the sense that the reinterpret_cast cannot remove const or volatile, whereas the C-style cast can. If you don't want to remove qualifiers then it's nice for the code to fail to compile when you get it wrong.
Of course, in this case there's little chance of getting it wrong -- the destination is const-qualified and you'd probably notice if the source was volatile-qualified. But it's still useful to get into the habit of letting the compiler help you, plus some people will consider the code easier to read.
If at all possible, add an overload for plain char, and hide the cast inside of the CRC class:
class crc32 {
// ...
unsigned int CRC(unsigned char const *in) {
// existing function
}
unsigned int CRC(char const *in) {
// pass through to preceding function:
return CRC(reinterpret_cast<unsigned char const *>(in);
}
};
I'd also note that at first glance crc32::CRC looks suspect to me. It looks like it may make more sense for this to be written as an overload of operator() instead.
So, I have two types at the moment:
const unsigned char* unencrypted_data_char;
string unencrypted_data;
I'm attempting to perform a simple conversion of data from one to the other (string -> const unsigned char*)
As a result, I have the following:
strcpy((unencrypted_data_char),(unencrypted_data.c_str()));
However, I'm receiving the error:
error C2664: 'strcpy' : cannot convert parameter 1 from 'const unsigned char *' to 'char *'
Any advice? I thought using reinterpret_cast would help, but it doesn't seem to make a difference.
You can't write to a const char *, because each char pointed to is const.
strcpy writes to the first argument. Hence the error.
Don't make unencrypted_data_char const, if you plan on writing to it (and make sure you've allocated enough space for it!)
And beware of strcpy's limitations. Make sure you know how big your buffer needs to be in advance, because strcpy doesn't stop 'til it gets enough :)
well if unencrypted_data_char point to a memory that is only readable,you'd better not to write any data on it,it will certainly cause a segment fault.
e.g:
const char *a="abc";
a pointed to a readable only memory
if unencrypted_data_char is const only because you let it be(like const char* a=b),well you could use const_cast< char* >(a) to conver it.
if converting from const char* to unsigned char*.
1.you need convert from const char* to char*.use const_cast.
2.conver from char* to unsigned char*. use reinterpret_cast.