Error: Cannot use unsigned char* to initialize CString.

Compiling on Solaris with gcc, the following code produces an error:

        ptText e;
        unsigned char* p = new unsigned char[strlen(word)];
        memcpy(p, word, strlen(word)+1);
        CString crypt =  e.code(p);

The compile error is:  Error: Cannot use unsigned char* to initialize CString.

How do I fix this ? (This code is based on the suggestion in a previous question.) Thanks.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Why not using a cast? E.g.
CString crypt =  e.code((char*)p);
// or
CString crypt =  e.code(static_cast<char*>(p));

Open in new window

evilrixSenior Software Engineer (Avast)Commented:
pillmill, haven't you now asked this same Q and variations of it number of times?


In all cases I'm sure the Q has been answered, although the Qs remain open and no follow-up has been received in any of them.
evilrixSenior Software Engineer (Avast)Commented:
Thanks jkr.
OWASP Proactive Controls

Learn the most important control and control categories that every architect and developer should include in their projects.

>>>> unsigned char* p = new unsigned char[strlen(word)];
>>>> memcpy(p, word, strlen(word)+1);

The code above allocates a buffer of size = strlen(word), while the memcpy copies strlen(word)+1 bytes to the buffer thus writing beyond the boundaries. That is very bad code and you shouldn't do it that way.

Note, the CString can provide a buffer of the requested length, e. g. like that

   // as 'word' compiles with strlen it most likely is a char*
   // then you simply can assign it to a CString

   CString text = word;

   // I assume the ptText::code takes an unsigned char* as argument
   // CString has a build-in cast operator for const char *
   // That means wherever a const char* (or LPCSTR) was needed for
   // argument type you can pass a CString instead

   // Unfortunately, if the argument type is const unsigned*  we need
   // casting, first (inner cast) to make the CString a const char*,
   // second (outer cast) to make the const char* a const unsigned char*
   // The last cast (from the right) is to make the return a const char*
   // what is one of the argument types a CString takes for constructing-

   CString crypt =  (const char*) e.code ((const unsigned char*)(const char*)text);

Note, I didn't use 'new' in the above and therefore is no need for a 'delete' either.

Note, instead of a C cast you could/should use C++ static_cast as evilrix showed. But as we not really do conversions with the above but only make the compiler happy with the casting, a C cast would do it as well.

pillmillAuthor Commented:
Here are the compile errors from:
CString crypt =  (const char*) e.code ((const unsigned char*)(const char*)text);

Error: Formal argument sText of type unsigned char* in call to static cryptText::code(unsigned char*) is being passed const unsigned char*.

 Error: Cannot use int to initialize CString.
pillmillAuthor Commented:
For CString crypt =  e.code((char*)p);
 // or
 CString crypt =  e.code(static_cast<char*>(p));

The compile errors are:
Error: "(" expected instead of "p".
Error: Using static_cast to convert from unsigned char* to char* not allowed.
Error: Cannot use int to initialize CString.

evilrixSenior Software Engineer (Avast)Commented:
What exactly is a ptText?

>> CString crypt =  e.code(static_cast<char*>(p));
Anyway, isn't it the result of e.code(p) you want to be casting?

>> Using static_cast to convert from unsigned char* to char* not allowed.
You cannot use static_cast as the pointer types are not compatible, it has to be reinterpret_cast.
CString crypt =  reinterpret_cast<char *>(e.code(p));
evilrixSenior Software Engineer (Avast)Commented:
>> Note, instead of a C cast you could/should use C++ static_cast as evilrix showed
I never showed that, it was jkr -- it should be reinterpret_cast to cast between incompatible pointer types. The only cast between pointer types static_cast can perform is from void * to T *
>>>> Formal argument sText of type unsigned char* in call to static cryptText::code(unsigned char*) is being passed const unsigned char*.

That is because the cryptText::code takes a non-const argument (what most likely means that it makes crypting by editing the passed buffer).

In that case you should provide a writeable buffer with CString like that:

     CString text = word;
     CString crypt =  (const char*) e.code ((unsigned char*)text.GetBuffer(text.GetLength()+1));

The GetBuffer returns a char*  (writeable up to requested size) which need to be casted to unsigned char* (writeable as well but looked on as pointer to unsigned char). I would assume that text and crypt have the same contents after encoding (what would mean that you can spare the assignment. ReleaseBuffer will correctly set the length and size members of the CString after GetBuffer by searching for the terminating zero char.

pillmillAuthor Commented:
CString crypt = (char *)e.code(p);
now compiles on Unix/Win32

CString crypt =(unsigned char*)e.code(p);
does not compile on Unix, but compiles on Win32.

Unfortunately, I must use an unsigned char for this method.
evilrixSenior Software Engineer (Avast)Commented:
>> I must use an unsigned char for this method.
Why do you think this? The bit representation of a char is the same as an unsigned char. You can still store binary data in a char -- look at ifstream.write, which supports writing binary data, this takes a char * as its first param. Did you see my example in your other Q?

{ http:Q_23462128.html#21755218 }
pillmillAuthor Commented:
class ptText
CString en(const CString& Text);
static unsigned char * code (unsigned char* Text);

ptText e;
CString crypt =  (unsigned char *) e.code(p);

For all suggestions, UNIX gcc still reports the error: "Cannot use unsigned char* to initialize CString".
Maybe I will have to use a (char *) ?

evilrixSenior Software Engineer (Avast)Commented:
>> Maybe I will have to use a (char *) ?
Can you please tell us why you think you have to use unsigned char? I have asked you this a couple of times now -- I am still awaiting an answer!

This is what the C++ Standard states...

"A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements; that is, they have the same object representation."

Basically, that means it really doesn't matter if you have an unsigned char * since you can simply cast it to a char * and know that it will still be representative of the same data. The STL makes consistent use of char * to represent binary data. Both iostream and string are binary data friendly, both implement this via a char *. It really doesn't matter that your CString expects a char *, if you really need an unsigned char * then just cast it back on the way out of the CString.
evilrixSenior Software Engineer (Avast)Commented:
BTW: If you are, as I suspect, using CStdString on Solaris, since you have the source code why don't you just modify it to use unsigned char if you really want it to?
>> Maybe I will have to use a (char *) ?

Look at my sample code. The correct cast is to (const char *) cause CString has a constructor taking that as only argument.

    CString crypt =  (const char*) e.code ((unsigned char*)text.GetBuffer(text.GetLength()+1));

>>>> static unsigned char * code (unsigned char* Text);

The reason why they take and return unsigned char * is cause encoding may turn a printable char (which are mostly codes from 32 to 126 ASCII) to a non printable char, which are either codes from 1 to 31 or many codes from 128 to 255. The latter range will turn to negative integers in the range from -128 to -1  if you look at them as signed chars cause the most significant bit turns to a sign bit. So if you would print a encoded text (casted to const char*) you most likely get all garbage output. It is much better to print the encoded text char as hex, e. g. code 255 as FF. That's why they use unsigned char cause they were printed as hex by default.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Unix OS

From novice to tech pro — start learning today.