I have a pointer to a string which is "unsigned char *" and i want to use it as an argument in strncmp() function.
But compiler complains:
invalid conversion from 'unsigned char*' to 'const char*'
How can i make:
strncmp(const char *a, unsigned char *b, size_t size);
work?
Is there any workaround?
You can safely cast unsigned into signed.
unsigned char * p2 = ...;
strncmp(px, (char *)p2, 5);
should work.
unsigned char * p2 = ...;
char * p3 = static_cast<char *>(p2);
This maybe overkill.
Not sure why you're using unsigned char*, but if you need to, use a cast. For example :
strncmp(a, (char*)b, 10);
use reinterpret_cast to convert it. Something like this -
strncmp(const char *a, reinterpret_cast<const char*>(unsigned char
*b), size_t size);
Related
I am currently working with a C-API (OpenSSL) and there are a lot functions declared like the following:
// From bytes to TYPE
TYPE *d2i_TYPE(TYPE **a, unsigned char **ppin, long length);
// From TYPE to bytes
int i2d_TYPE(TYPE *a, unsigned char **ppout);
But sometimes, functions expect a pointer to an array of pointers to some const type:
// From bytes to TYPE
TYPE *d2i_TYPE(TYPE **a, const unsigned char **ppin, long length);
Notice the const unsigned char ** vs unsigned char ** and ignore the functions' first argument.
Now consider the following example, where some input data is given as non-const pointers. What is the correct way of casting the array of pointers to an array of pointers const? And also, since the function expects a pointer, the parameter must be an lvalue. I am guessing this is the reason there is no implicit cast..
int length = 42;
unsigned char * data = new unsigned char[length];
// Error C2664: cannot convert argument 2 from 'unsigned char **' to 'const unsigned char **'
TYPE * my_typeE = d2i_TYPE(nullptr, &data, length);
// My solution:
auto x = reinterpret_cast<unsigned char const *>(data);
auto y = const_cast<unsigned char const *>(data);
TYPE * my_typeX = d2i_TYPE(nullptr, &x, length);
TYPE * my_typeY = d2i_TYPE(nullptr, &y, length);
Are there other solutions that are possibly easier to read?
No need of cast:
const unsigned char* z = data;
[[maybe_unused]]TYPE * my_typeZ = d2i_TYPE(nullptr, &z, length);
Demo
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 get an error "Cannot initialize a parameter of type "const unsigned char *" with an rvalue of type 'value_type ' (aka char)" in the following lines.
image->initWithImageData(&(buffer->front()),buffer->size());
buffer is of type std::vector<char> *buffer
and the above error in on &(buffer->front() does anybody know how to fix it?
The const is not a problem, but you need to cast the pointer - this isn't recommended generally but if you don't have another choice, you can do one of the following
char *a = buffer->data();
const unsigned char *b= reinterpret_cast<unsigned char *>(a);
or plain C style
const unsigned char *b= (const unsigned char *)(a);
I have following code, it's code from tomcrypto's manual and it won't work on MS VC++ 2008 EE. Any help? Also can I ask replace char* by std::string object?
int main(void)
{
hash_state md;
unsigned char *in = "hello world", out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, in, strlen(in));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Errors:
\main.cpp(7) : error C2440: 'initializing' : cannot convert from 'const char [12]' to 'unsigned char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(11) : error C2664: 'strlen' : cannot convert parameter 1 from 'unsigned char *' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
EDIT: Now code looks like:
int main(void)
{
register_hash(&md5_desc);
hash_state md;
char* p = "hello wordl";
unsigned char *in = reinterpret_cast<unsigned char*>(p);
char* out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, const_cast<char*>(in), strlen(in));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Errors:
\main.cpp(21) : error C2440: 'const_cast' : cannot convert from 'unsigned char *' to 'char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(21) : error C2664: 'strlen' : cannot convert parameter 1 from 'unsigned char *' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(23) : error C2664: 'md5_done' : cannot convert parameter 2 from 'char *[16]' to 'unsigned char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
unsigned char *in = "hello world"
This is incorrect in C++: "hello world" is a string literal and is of type const char[12]. In C it is of type char[12], but the const here doesn't matter because in C++ there is an implicit (but deprecated) conversion that allows a string literal to be converted to a char*.
The problem is that char and unsigned char are different types. It doesn't matter whether char is unsigned; the three char types (char, unsigned char, and signed char) are all distinct and in C++ you cannot convert between pointers to those three types without a cast.
This works in C because in C you can convert any pointer-to-object type to any other pointer-to-object type without a cast. That isn't the case in C++.
In C++ you would need to use:
// use the implicit conversion to 'char*' to cast away constness:
char* p = "hello world";
// explicitly cast to 'unsigned char*'
unsigned char* in = reinterpret_cast<unsigned char*>(p);
The removal of constness is usually a bad idea since string literals are not modifiable, but sometimes it is necessary when dealing with legacy libraries that are not const-correct.
The conversion from char* to unsigned char* is safe because all objects can be treated as an array of char, unsigned char, or signed char in C++.
char is a different type to signed char or unsigned char; string literals are always of type (const) char *; so you cannot assign them to a (const) signed char * or a (const) unsigned char *. To fix this, remove the unsigned from line 4.
If your md5_process() function explicitly takes an unsigned char * as an argument, then you should perform a cast at that point:
md5_process(&md, reinterpret_cast<unsigned char*>(in), strlen(in));
[As others have said, you should really define in as const char *in as it's pointing to a string literal, but that is not the issue here.]
Let's try again:
int main(void)
{
register_hash(&md5_desc);
hash_state md;
const char* p = "hello wordl";
const unsigned char* in = reinterpret_cast<const unsigned char*>(p);
unsigned char out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, in, strlen(p));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Does this work?
This is because litteral strings are const in C++, while you initialize it with a non-const pointer:
const char* in = "hello world";
char * out[16];
However it might cause a problem if md5_process takes a non-const char*, in this case you'll have to cast to a non-const:
md5_process(&md, const_cast<char*>(in), strlen(in));
I have a method that takes unsigned chars, but I want to pass it 0x01.
I know I can represent hex chars in strings by going "\x01"...
but that is still a signed char.
EDIT:
some code:
kennys_hash((unsigned char const *)"\x00"); // the method call
the error:
src/main.cpp:88: error: invalid conversion from ‘const unsigned char*’ to ‘unsigned char’
src/main.cpp:88: error: initializing argument 1 of ‘unsigned char kennys_hash(unsigned char)’
the method header:
unsigned char kennys_hash(unsigned char out)
ALso, when the cast is just to unsigned char, I get this error:
src/main.cpp:88: error: cast from ‘const char*’ to ‘unsigned char’ loses precision
0x01 is the same as 1, which is positive, and thus it doesn't matter if it's considered to be signed or unsigned, the value is the same.
If you want to have an unsigned type on the literal, use 0x01u.
Note that "\x00" is an string constant (read: array of char), and not a single character constant.
Use single quotes: '\x00' is a character constant.
The type might be char, but that is automatically converted to unsigned char when needed. Some compilers might issue a warning though.
You can use boost::lexical_cast:
unsigned char bar = boost::lexical_cast<unsigned char>( "\x71" );
void foo(unsigned char const * u);
...
foo( (unsigned char const *) "\x01");
You can pass it an array of unsigned chars, like this:
unsigned char data[5] = {1, 2, 3, 4, 5};
func_that_takes_unsigned_chars(data, sizeof data);
I bet you can't send it \x-01. Therefore you are sending it an unsigned int.
You can always test you your input before you send it to the func. If inp < 0 then send it back.