Link to home
Start Free TrialLog in
Avatar of pillmill
pillmill

asked on

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.
Avatar of jkr
jkr
Flag of Germany image

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

pillmill, haven't you now asked this same Q and variations of it number of times?

http:Q_23462128.html
http:Q_23461584.html
http:Q_23443185.html

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.
Thanks jkr.
>>>> 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.


Avatar of pillmill
pillmill

ASKER

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.
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.

Thanks.
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));
http://www.cppreference.com/keywords/reinterpret_cast.html
>> 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));
     text.ReleaseBuffer(-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.

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.
>> 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 }
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 *) ?


>> 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.
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?
ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial