Solved

Error: Cannot use unsigned char* to initialize CString.

Posted on 2008-06-10
17
1,255 Views
Last Modified: 2013-12-27
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.
0
Comment
Question by:pillmill
  • 7
  • 4
  • 3
  • +1
17 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
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

0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
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.
0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
Thanks jkr.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> 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.


0
 

Author Comment

by:pillmill
Comment Utility
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.
0
 

Author Comment

by:pillmill
Comment Utility
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.
0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
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
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 40

Expert Comment

by:evilrix
Comment Utility
>> 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 *
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> 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.

0
 

Author Comment

by:pillmill
Comment Utility
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.
0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
>> 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 }
0
 

Author Comment

by:pillmill
Comment Utility
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 *) ?


0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
>> 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.
0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
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?
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 125 total points
Comment Utility
>> 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.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now