Is it allowed to cast a char[] to unsigned char *? - c++

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.

Related

How to convert string to const unsigned char* without using reinterpret_cast (modern approach)

I have variable input type const std::string&:
const std::string& input
Now I need to convert this to const unsigned char* because this is the input of the function.
Unitl now I have correct code for converting:
reinterpret_cast<const unsigned char*>(input.c_str())
This works well, but in clang I got a warning:
do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
What is the correct way to change a string or const char* to const unsigned char*?
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 accept char* 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.
Edit
Apparently type punning with an union is UB so definitely don't do this.
(Keeping the answer for posterity though!)
To strictly answer your question, there's this way:
void foo(const unsigned char* str) {
std::cout << str << std::endl;
}
int main()
{
std::string word = "test";
//foo(word.data()); fails
union { const char* ccptr; const unsigned char* cucptr; } uword;
uword.ccptr = word.data();
foo(uword.cucptr);
}
Is this any better than a reinterpret_cast? Probably not.

Warning generated due wrong strcmp parameter handling

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 )

cannot convert from 'const char *' to 'char *' for std::string::c_str

This gives the error: cannot convert from 'const char *' to 'char *'.
class Mock
{
public:
...
static void func(char **result)
{
*result = (resultsI++)->c_str();
}
static std::vector<std::string> results;
static std::vector<std::string>::iterator resultsI;
};
std::vector<std::string> Mock::results;
std::vector<std::string>::iterator Mock::resultsI;
How can I validly get rid of this error without changing the interface to the function func? The implementer of this interface:
void (func*)(char **result)
forgot to use const char** in the signature. I can't change it.
Remember this is a mock and I'm only used in my unit tests.
Try:
*result = &(*resultsI++)[0];
Although this isn't guaranteed to work prior to C++11 it is known to be OK on most or all current compilers.
The danger is that if the function tries to change the length of the string, you could get some nasty errors. Changing individual characters should be OK.
In test code, and if you are certain that the user of the interface isn't going to mutate the char*, maybe you could use a const_cast?
That assumes the caller doesn't take ownership of the char *; if that is the case, then you should make a copy.
If you're absolutely certain that the interface function will not modify the string, you can use
*result = const_cast<char *>((resultsI++)->c_str());
to remove constness.
Otherwise, another option is to switch from using std::vector<std::string> to std::vector<std::vector<char>> but then you'll have to make sure you properly null terminate the strings.

Deprecated conversion from string constant to char * error [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ deprecated conversion from string constant to ‘char*’
I am having following code, though i didn't copy full code because it is huge.
Following code is in template class, and i am getting warning as below. Because of warning in template i am not able to instantiate it and getting "instantiated from here" error.
warning: deprecated conversion from string constant to 'char*''
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}
char cCompleteMessage[200];
memset(cCompleteMessage, 0x00, sizeof(cCompleteMessage));
char*cMessage = "add reorgenize failed";
ErrorMessageInRaphsodyCode(cCompleteMessage, cMessage, "omcollec.h", __LINE__);
My question is what is best way to get rid of above warning ?
If a function takes a char const *, it guarantees that it only reads whatever data the pointer points to. However, if it takes a non-const pointer, like char *, it might write to it.
As it is not legal to write to a string literal, the compiler will issue a warning.
The best solution is to change the function to accept char const * rather than char *.
char cMessage[] = "add reorganize failed";
This should get rid of the warning.
Best way to get rid of it is to fix the function that is taking the parameter.
If your code is correct and the function does indeed take string constants, it should say so in its prototype:
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, const char* pcFileName, unsigned int RowNo)
If you can't do that (you don't have the code), you can create an inline wrapper:
inline void ErrorMessageInRaphsodyCodeX(char* p1, char* p2, const char* p3, unsigned int p4)
{ ErrorMessageInRaphsodyCode(p1,p2,(char*)p3,p4); }
and use the wrapper instead.
If your code is incorrect and the function does actually require writeable memory (which I highly doubt), you will need to make the string writeable by either creating a local array as Jan suggested, or mallocating enough memory.
(1) Make the variable a const char*
(..., const char* pcFileName, ...)
(2) If above is not possible and you want to retain the state of char* and const char* then make the function a template:
template<typename CHAR_TYPE> // <--- accepts 'char*' or 'const char*'
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, CHAR_TYPE* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}
function c_str() of std::string class.

Const unsigned char* to char*

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.