So I have an
unsigned char * pMyPtr
assigned to something.
Then I want to compare this to an arbitrary string with
strcmp(const char* , const char* )
But when I do that, clang compiler tells me
warning: passing (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign
How do I remove this warning?
With all the comments to the question, I feel like I'm missing something.
I know that casts are unfashionable, but isn't the following a simple workaround?
strcmp((const char*) pMyPtr , whatever_is_being_compared)
It isn't even unsigned. Behind it, is a struct.
This means that you cannot use strcmp here. You can use strcmp when the input data are null-terminated strings. That's not the case when the input data are structs. Perhaps you should consider memcmp instead, or perhaps you need to compare the structs as structs.
Clang can't convert from unsigned char* to const char*.
That because unsigned char* is different then char*.
By adding unsiged you make the range of char 0to255 instead of -127to127.
On the line where strcmp goes, you can typecast the unsigned char value with (const char*) which will work, because there it will be threated as a const char*. instead of unsigned char
If you feel that warning does not have any side effect. you can ignore the warning like this:
#pragma warning( disable : 4507 34 )
Related
I need to use methods described in RFC2617 and RFC1321, but am getting problems about converting C to C++. Mostly I have problem with a parameter is defined as unsigned char but argument is a char* variable.
I can solve errors with reinterpret_cast but thought there would be a better way, because there is lot of changes need to be done.
For example in the following line in md5c.c variable pszUserName is declared as char*, if the variable changed to unsigned char*, then strlen got errors:
IN char * pszUserName,
...
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
Declaration of MD5Update
void MD5Update (
MD5_CTX *context, /* context */
unsigned char *input, /* input block */
unsigned int inputLen /* length of input block */
)
{
...
}
I got this error in the first place:
../Dig/digcalc.cpp: In function ‘void DigestCalcHA1(char*, char*, char*, char*, char*, char*, char*)’:
../Dig/digcalc.cpp:44:58: error: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive]
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
There is also a nice copy in Github
Technically, char, unsigned char and signed char are types incompatible with each other. The code:
MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
"should" be:
MD5Update(&Md5Ctx, (char *)pszUserName, strlen(pszUserName));
However, in my opinion, this is all rather annoying. MD5Update works equally well on char as unsigned char; we shouldn't have to make the code less readable for no real reason.
On existing codebases that use char * and unsigned char * interchangeably like this, I enable the compiler flag -Wno-pointer-sign and don't feel bad about it. It keeps the code more readable and the compiler behaves as if there were a cast.
I have read a lot about the subject and I am confused .
What used to work in a C file ,not working on a cpp file :
char *builtinFunctions[20];
Then I get error on the strcpy function here :
void Intepreter::setBuiltIns(char *builtins)
{
strcpy(builtinFunctions, builtins); // no matching function call to strcpy
}
I probably don't understand the basics here, but why in C++ this will not work ( do i need to use = instead ? )
strcpy(char *, const char*) = thats the structure
if I change the builtinFunctions from being a pointer it works.
EDIT:
The reason for being a const before this edit is that I read here :
Why is conversion from string constant to 'char*' valid in C but invalid in C++
that char *builtinFunctions[20]; will produce warning when :
builtinFunctions[0]="me";
and it did. I could fix it by removing the const .
This is an array of pointers to char.
char *builtinFunctions[20];
So you call
strcpy(builtinFunctions, builtins);
gets treated as strcpy(char **, char*), not as strcpy(char *dest, const char *src). So you get a mismatch for first parameter type.
EDIT:
So let's suppose builtinFunctions is "an array of words" you wish to populate, with void Intepreter::setBuiltIns(char *builtins) meant to do just that with it's first parameter being a pointer to a new incoming word. (And you're doing this in a C-style manner. Well, up to you.)
Some things to consider.
If you declare an array type arrName[N]; then the array's name
being used all alone without index is treated as a variable of type
type *arrName. If you type is initially char *, then
builtinFunctions by itself is of type char**. That's why your
strcpy fails, but strcpy(builtinFunctions[someIndex], builtins);
works.
Before invoking strcpy you should consider, if you have a
destination space allocated. builtinFunctions[someIndex] is of
type char *. Where does it point to? Is it a valid pointer to an
allocated space, or a gateway to hell of undefined behaviour strcpy will happily take you to?
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.