Code::Blocks Forums

User forums => General (but related to Code::Blocks) => Topic started by: sethjackson on February 05, 2006, 10:22:34 pm

Title: Compile error
Post by: sethjackson on February 05, 2006, 10:22:34 pm
Hi I get this error

error: incompatible types in assignment of `int' to `unsigned char*[((unsigned int)((int)imageSize))]'

with this code......

Code: cpp
if (image.HasAlpha())
{
        unsigned long imageSize = image.GetWidth() * image.GetHeight() * 4;
        unsigned char* imageData = image.GetData();
        unsigned char* imageAlpha = image.GetAlpha();
        unsigned char* data[imageSize];

        for (unsigned long index = 0; index < imageSize; index += 4)
        {
            memcpy(data, imageData, 3);

            imageData += 3;

            memcpy(data + 3, imageAlpha, 1);

            imageAlpha++;

            data += 4;
        }

        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.GetWidth(), image.GetHeight(),
                          GL_RGB, GL_UNSIGNED_BYTE, data);
}


Help me please...... Sorry for the beginner question? I just don't get it I used to do stuff like increaseing the ptr with += all the time.....

EDIT:

Let me say that it fails on the line

Code: cpp
data += 4;

 :P
Title: Re: Compile error
Post by: sethjackson on February 05, 2006, 10:35:42 pm
Ok I fixed it now could someone tell me why this works???

Code: cpp
*(data) += 4;
Title: Re: Compile error
Post by: polygon7 on February 05, 2006, 10:38:49 pm
Hi,
this should work
Code
if (image.HasAlpha())
{
        unsigned long imageSize = (image.GetWidth() * image.GetHeight())  << 2;
        unsigned char* imageData = image.GetData();
        unsigned char* imageAlpha = image.GetAlpha();
        unsigned char* data[imageSize];
 
        for (unsigned long index = 0; index < imageSize; index += 4)
        {
            memcpy(data, imageData, 3);
 
            imageData += 3;
 
            memcpy(data + 3, imageAlpha, 1);
 
            ++imageAlpha;
 
           (*data) += 4;
        }
 
        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.GetWidth(), image.GetHeight(),
                          GL_RGB, GL_UNSIGNED_BYTE, data);
}
// Edit: Ah, you're faster :P
Code
char* array[size]
is the same as
Code
char** array
Title: Re: Compile error
Post by: sethjackson on February 05, 2006, 10:40:22 pm
 :lol: :lol: Read my post above. Exactly why does it work though? Thanks.  :D
Title: Re: Compile error
Post by: Michael on February 05, 2006, 10:49:43 pm
:lol: :lol: Read my post above. Exactly why does it work though? Thanks.  :D

You tried to assign an int to an unsigned char*. This does not work for sure. What do did is to de-reference the pointer. Then it works.

Why you cast before int and then unsigned int?

Anyway, do not use C-cast style. This is not a good idea in C++. You should use C++ cast style or better no cast at all (if possible).

Best wishes,
Michael
Title: Re: Compile error
Post by: sethjackson on February 05, 2006, 10:55:55 pm
@polygon7

Why the
Code: cpp
<< 2
instead of
Code: cpp
 * 4
?

This line

Code: cpp
unsigned long imageSize = (image.GetWidth() * image.GetHeight())  << 2;

@Michael How to use a C++ style cast in this case??? Yes I know static_cast, dynamic_cast etc. How to use it here???
Title: Re: Compile error
Post by: polygon7 on February 05, 2006, 11:01:47 pm
@polygon7

Why the
Code: cpp
<< 2
instead of
Code: cpp
 * 4
?

This line

Code: cpp
unsigned long imageSize = (image.GetWidth() * image.GetHeight())  << 2;
"<<" is shifting bits operator (shift left, SHL in assembly). SHL can be used for multiply by power of two (SHR, shift right for dividing by power of two).

x*2 == x <<1, x*4 == x <<2 ...

Bit shifting usually is faster then normal multiply.
Title: Re: Compile error
Post by: Michael on February 05, 2006, 11:17:09 pm
@Michael How to use a C++ style cast in this case??? Yes I know static_cast, dynamic_cast etc. How to use it here???

In your case and if I am not wrong, I would use the static_cast Operator:

Quote
static_cast<T> (expr)
To convert the expression expr to type T. Such conversions rely on static (compile-time) type information.

Anyway, I am not an expert in C++ cast as usually I used C cast until I discovered that are not so good (cast is already ugly, but C-cast is uglier). You can get some useful info here:


You can also have a look at this topic (http://forums.codeblocks.org/index.php?topic=1592.0).

Michael
Title: Re: Compile error
Post by: sethjackson on February 06, 2006, 12:01:07 am
Ok guys thanks. I learnt something today. :)

@Michael yeah I always use C++ casts instead of C casts. I couldn't figure out how to get it to work here. What type do I need to static_cast to?? I tried static_cast, but I couldn't figure out which type to cast to.  :P
Title: Re: Compile error
Post by: Michael on February 06, 2006, 12:14:44 am
@Michael yeah I always use C++ casts instead of C casts. I couldn't figure out how to get it to work here. What type do I need to static_cast to?? I tried static_cast, but I couldn't figure out which type to cast to.  :P

For example, you can use it to cast a double to an int:

Code
double myDouble = 3.0;
int myInt = static_cast<int>(myDouble);

Anyway, be careful because static casts could be dangerous.

Have a look at the links I have suggested. There is a lot of examples and useful bla bla :).

Michael
Title: Re: Compile error
Post by: sethjackson on February 06, 2006, 03:05:57 am
Ok I'll check it out tomorrow hopefully.  :lol:
Title: Re: Compile error
Post by: sethjackson on February 06, 2006, 07:18:09 pm
I tried

Code: cpp
static_cast<unsigned char* []>(data) += 4;

and it didn't work.

Code
error: invalid static_cast from type `unsigned char*[((unsigned int)((int)imageSize))]' to type `unsigned char*[]'

What type (int, char, etc.) do I need to cast to???
Title: Re: Compile error
Post by: sethjackson on February 06, 2006, 07:23:17 pm
Nevermind. This works, and better too I think. :)

Code: cpp
if (image.HasAlpha())
{
        unsigned long imageSize = image.GetWidth() * image.GetHeight() * 4;
        unsigned char* imageData = image.GetData();
        unsigned char* imageAlpha = image.GetAlpha();
        unsigned char* data = new unsigned char[imageSize];

        for (unsigned long index = 0; index < imageSize; index += 4)
        {
            memcpy(data, imageData, 3);

            imageData += 3;

            memcpy(data + 3, imageAlpha, 1);

            ++imageAlpha;

            data += 4;
        }

        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.GetWidth(), image.GetHeight(),
                          GL_RGB, GL_UNSIGNED_BYTE, data);

        delete[] data;
}
Title: Re: Compile error
Post by: Michael on February 07, 2006, 10:42:10 am
Hello,

When you use new you should check if the memory has been reserved or not. If I remember correctly the new sends a bad_allocation exception if it fails. Another version of new just a null pointer (which could or not be a better alternative :)).

Best wishes,
Michael
Title: Re: Compile error
Post by: killerbot on February 07, 2006, 11:13:51 am
Hello,

When you use new you should check if the memory has been reserved or not. If I remember correctly the new sends a bad_allocation exception if it fails. Another version of new just a null pointer (which could or not be a better alternative :)).

Best wishes,
Michael


Normally when new fails, it throws -> catch it.
There exist a no_throw new. I think it is not portable, the gurus (Sutter, ..) give the advice not to use it. So just forget you ever heard about it ;-)
Title: Re: Compile error
Post by: Michael on February 07, 2006, 11:58:50 am
Normally when new fails, it throws -> catch it.
There exist a no_throw new. I think it is not portable, the gurus (Sutter, ..) give the advice not to use it. So just forget you ever heard about it ;-)

Normally, I always use the throw new :). But, there was a mention of the no-throw new in the book C++Primer (4th Edition) written by
Stanley B. Lippman et al. I will give a check in the C++ standard book later. Until now, I have just found that you can overload the operator, but how this will influence the portability, it was not written :(.

Michael
Title: Re: Compile error
Post by: sethjackson on February 07, 2006, 07:39:29 pm
How do I use try/catch?

Code: cpp
        unsigned char* data;

        // Try to allocate some memory.

        try
        {
             data = new unsigned char[imageSize];
        }

        // Show an exception message if we can't allocate the memory we need.

        catch(bad_allocation)
        {
            wxSafeShowMessage(_("Exception"), _("Memory allocation failed! The application will terminate immediately..."));
        }


Sorry I'm new to this type of error handling....  :P
Title: Re: Compile error
Post by: thomas on February 07, 2006, 07:48:33 pm
You need to provide a type in the catch ( ) clause. Except for that, it's ok.

Alternatively, you can use catch ( ... ) if you want to catch all. Then, however, you don't know what you have caught (often, that's acceptable).

EDIT:
Oh yes... the reason why you have to provide a type is that you can catch different things from the same try block (in case that more than one thing can go wrong). The catch block whose type matches the exception thrown is executed and you get the exception similar to a function argument.
Title: Re: Compile error
Post by: thomas on February 07, 2006, 08:01:30 pm
Another thing: You are using exceptions in an OpenGL application. I don't know what exactly you're programming there, but if it is something that is really CPU-intensive (which may happen to be the case here), then you should be aware that exceptions are not free.

Catching an exception (which luckily only happens in the exceptional case) takes a lot of CPU time, on the order of tens to hundreds of microseconds.
However, even if you do not throw and catch exceptions, your code runs somewhat slower (something on the order of 2-4%, depending on the compiler and the program). Often, this does not matter much, but then, sometimes it does. Thus, think clearly whether you really need exceptions in a CPU-intensive application.
Title: Re: Compile error
Post by: Game_Ender on February 08, 2006, 02:16:50 am
Thomas makes a good point but I don't you think you should throw them away out of hand.  Almost everyone spends time making "optimizations" on areas that don't need any.  I say use exceptions carefully and if you run into performance problems pull back there use.

Take a look at Ogre (http://www.ogre3d.org).  It is a high performance 3D rendering engine.  It uses exceptions, but only where they are appropriate, like when a resource fails to run or you have done something to crash the render system.

The overall important rule for exceptions to use them for program flow control, that means don't check for thing with exceptions.  This rough java snippet below is a good example of what not to do:

Code: java
int[] myArray = new int[10];

try {
  int index = 0;
  while(true) {
    system.out.println(myArray[index])
    index++;
  }
} catch (ArrayIndexOutOfBoundsException e)
  // Finished the loop
}

Title: Re: Compile error
Post by: thomas on February 08, 2006, 10:04:56 am
Right, like I said, sometimes it does not matter, and sometimes it does. Although I disagree on Ogre ;)
Ogre is a good example where I think exceptions are actually out of place. It certainly works. And it works excellent, too. But the main purpose of Ogre is to create games. Today, the GPU usually has plenty of cycles left while on the other hand, the game is utterly CPU-bound. You have to try very hard to be GPU-bound (unless you write very very expensive shaders).
Thus, it seems to me that losing a couple of percent of CPU time to exception handling may not precisely be what you want to do.
Of course, things like scripting easily eat up 10-20 times as much CPU as EH, but you usually cannot do without scripting.

The problem with EH is that even if you only use exceptions where appropriate, you can only compile with or without exception handling, and unless you use compiler-specific attributes (such as nothrow), the compiler has a very hard time knowing where to add stack unwinding code and where not to (most will simply insert code everywhere).
Title: Re: Compile error
Post by: Michael on February 08, 2006, 11:19:44 am
There exist a no_throw new. I think it is not portable, the gurus (Sutter, ..) give the advice not to use it. So just forget you ever heard about it ;-)

I have had a look at the C++ Standard book and I have found that the two possibilities for the operator new are described and there are no constraints in using the throw-new instead of the nothrow-new. There is written something as: "If the program wishes...". Personally, I have never used the nothrow-new, but I prefer it, even if I have to specify nothrow, e.g.:

Code
int* ndata = new(nothrow) int;
//do something with ndata
delete ndata;

I have also not found portability issues by searching with Google. May be this is due on how C++ standard compliant are the different compilers.

Michael
Title: Re: Compile error
Post by: jmccay on February 09, 2006, 02:31:29 am
@polygon7

Why the
Code: cpp
<< 2
instead of
Code: cpp
 * 4
?

This line

Code: cpp
unsigned long imageSize = (image.GetWidth() * image.GetHeight())  << 2;
"<<" is shifting bits operator (shift left, SHL in assembly). SHL can be used for multiply by power of two (SHR, shift right for dividing by power of two).

x*2 == x <<1, x*4 == x <<2 ...

Bit shifting usually is faster then normal multiply.

I would like to add (because not everybody might know it) that there is one advantage to using the bit shifting operators over a normal multiplication/division.  On some systems (since I don't know all systems and my assembly language is rusty I will use "some"), the operator translates to an assembly/machine language command that is faster than multiplication & division.  It was/is a technique used by game developers for faster mathematics when manipulating images.  They would make the images multiples of 2 to be able to use it.

jmccay
Title: Re: Compile error
Post by: Ceniza on February 09, 2006, 03:16:04 am
Well, if you take a look at the compiler's output, even without optimizations (GCC), using * 4 or << 2 generate the same code, but * 4 is still more readable.

For this code:
Code: cpp
b = a * 4;

The compiler outputs:
Code: asm
movl	-4(%ebp), %eax
sall $2, %eax
movl %eax, -8(%ebp)

There're many things compilers can handle by themselves, including such simple optimizations, and a few more advanced ones that can only be achieved in ASM.

Specifying optimizations (like -O3) will give you better results, like converting:
Code: cpp
b = a * 5;

into:
Code: asm
movl	-4(%ebp), %edx
leal (%edx,%edx,4), %eax
movl %eax, 4(%esp)

As you can see those early optimizations just make your code less readable for the same output and performance.