cast unsigned char to int

21 Mar 2011

Hi guys,

i've got a big problem.

I've got an unsigned char buffer[255]. I have stored an integer-value in buffer[12]. but when i want to restore the value in buffer[12], the program stops and the cast is not executed.

code of the cast:

unsigned char buffer[255];

int i = 17;

buffer[12] = i; works perfectly

later:

int j = buffer[12]; doesnt work

i've tried lots of implicit and explicit casts, but nothing works. whats the problem? my code should work fine.

thanks

johannes

21 Mar 2011

Does this work ?

int j = (int)buffer[12];

if not, what is the error ?

21 Mar 2011

I think this is a dough ! Moment,

You array is 12 and you are usin element 13. Array references [0..12] Would need .....[13] :) Ceri

21 Mar 2011

Quote:

but when i want to restore the value in buffer[12], the program stops and the cast is not executed.

What do you mean by the program stops? Does the compiler give you an error here or do you know that the program never gets past this point since it doesn't execute a printf() or something similar that you have following the read out of buffer[12]?

21 Mar 2011

ceri clatworthy wrote:

I think this is a dough ! Moment,

You array is 12 and you are usin element 13. Array references [0..12] Would need .....[13] :) Ceri

His array is 255 long, so [0..254], I think the index [12] is correct, and is also irrelevant to the problem.

I have a problem that is extremely similar to the one Johannes is having. I'm still struggling getting code that works on GNU to work on RealView.

unsigned char getch()
{
    // some stuff ...
    return something;
}

void foo()
{
    int length = 256 * getch() + getch();
    
    for (int i = 0; i < length; i++)
    {
        // do something
    }
}

The problem is that when the 1st getch() returns 0 and 2nd getch() returns 0x80, the variable "length" should ideally be 128, but the for loop runs more than 128 times, it's almost as if the return value from getch() was type casted to signed char before being added to the "length" variable.

I thought paying for mbed to test RealView would be a good idea, but it doesn't seem that great anymore... ARM needs to fix stuff like this.

21 Mar 2011

Hi Frank,

In your example, I think actually both compilers are giving you a perfectly correct result. However, the results are different based on the ambiguity of your program itself!

Remember, in C, expressions can be evaluated in any order. So that means what you are assuming is the result of the first getch call may infact be the second. So in your code, you may perfectly validly get the calculation:

int length = 256 * 0 + 0x80  // 0x80
 - or -
int length = 256 * 0x80 + 0  // 0x8000

and both conform to your program specification. So in the case when you say it runs more than 128 times, I suspect the result is actually the second one. The following example program shows the behaviour:

#include "mbed.h"

unsigned char getch() {
    static int first = 1;
    if(first) {
        first = 0;
        return 0;
    } else {
        return 0x80;
    }
}

int main() {
    int length = 256 * getch() + getch();
    printf("length = %d\n", length);    
}

gives:

length = 32768

as expected. So I think the compiler is fine :)

I suspect the first problem in this thread is similarly unrelated to where the problem "appears" to be. If you've looked so hard for the problem that it can't be anything but the compiler broken, it is often actually just you are looking in the wrong place! A good debug method is to talk through the logic of your program to the cardboard cutout/rubber duck/teddy.

Hope that is useful.

Simon

21 Mar 2011

but multiply has higher precedence than addition, it also has left associativity, and is specified first

even if what you said is true, I think the order is not ambiguous in this case

21 Mar 2011

I hate to disagree with Simon, but I believe he is mistaken here.

The C standard calls for an evaluation of operands, in the absence of parentheses, in a precedence order defined by the standard. Additive operands (+ -) are assigned precedence 12 and multiplicative (* / %) operands are assigned a precedence of 13.

So the evaluation is determinate, the multiplication occurs before the addition.

I think the ambiguity is in the getch() function and its presentation of "extended characters."

When certain keys are pressed either an X’00’ or an X’ED’ is presented first and the presence of either of these values signal that there is a second character to follow which should be interpreted as an extended character.

21 Mar 2011

Hi Frank, Harry,

Careful not to confuse operator precedence with sequence points. You are exactly right that the multiply has higher precedence than the addition (i.e. the multiply is done before the addition), but that is not actually the same as requiring the results of the function that is used by the multiply to be evaluated before the function used by the add. The + and * operators are not sequence points, only the ;

Take a look at Sequence Points in C to read more. Paragraph 2 is all about this sort of ambiguity :)

I'll reserve the right to be wrong, but I think this is just one of those things that is a bit annoying in C!

Simon

21 Mar 2011

Lesson learned, thanks, I'll notify the author of the code I'm trying to port.

21 Mar 2011

Frank 26080115 wrote:

the return value from getch() was type casted to signed char before being added to the "length" variable.

People, you are all right and all wrong to certain extend.

what ever the case, base on getch returns signed char as quoted above.

int length = 256 * getch() + getch();

will give length <= 128 only when first get is 0 and 2nd get is <= 0x7f. As soon getch() return a value >= 0x80, it will convert to a negative value integer. So a get return 0xff = -1 integer, 0x80 = -128.

by default char is a signed value.

so in your example second getch gives 0x80 & 1st gives 0, you get length = -128. The loop should not looped at all.

lastly, what guaranty you the first get returns 0. The key press is buffered, by doing 2 consecutive getch, you can actually read 2 key pressed. So it could well read 'a' & 'a' or 'a' & 'd' or 'c' & '\0' or '\0' & 'a' ...

So the assumption of reverse key order by Simon is correct.

but the length value is still negative

21 Mar 2011

Yoko Hama wrote:

by default char is a signed value.

Not according to this page.

22 Mar 2011

Yep, on ARM char is traditionally unsigned. The reason is that until recently, ARM didn't have fast instructions to handle signed 8-bit and 16-bit elements.

22 Mar 2011

I don't think char should have EVER been signed. Except a few rare cases on teeny micros where the dynamic range of 8 bits can mean something.

22 Mar 2011

Igor Skochinsky wrote:

Yep, on ARM char is traditionally unsigned. The reason is that until recently, ARM didn't have fast instructions to handle signed 8-bit and 16-bit elements.

Thanks for the precision, as this is my first experience on ARM platform. As with other platforms, I worked on. Char is always default signed to be the same as other type (int, long, ect..). When not specified unsigned, is by default signed.

22 Mar 2011
22 Mar 2011

Sorry guys, but my problem still lasts^^

I can't cast an unsigned char to an integer. why is that so and how can I work around this obvious bug?

thanks again.

22 Mar 2011

Yoko Hama wrote:

Does this work ?

int j = (int)buffer[12];

if not, what is the error ?

there is no error in the compiler, all fine. the program just won't go further from this point., the cast is not executed.

22 Mar 2011

main.cpp

#include "mbed.h"

Serial pc(USBTX, USBRX);

unsigned char buffer[256];

int main() {
    int j, i = 17;
    
    pc.baud(115200);
    
    buffer[12] = i;
    
    j = (int)buffer[12];
    
    pc.printf("j = %d\n", j);
    
    while(1) ;    
}

Output

j = 17

I can't see what you are getting at? Can you reduce your problem to a very simple program like the above so that we can compile and try?

22 Mar 2011

Are you able to share more of your code? This sounds like it might be a memory issue (alignment or an attempt to access invalid memory.) What kind of code is executing between your setting of the buffer[12] element and your attempt to read it? Is it possible something goes wrong before you get to the read from this array or does your code make it to a printf() placed before the read but not one placed after?

22 Mar 2011

Adam Green wrote:

Are you able to share more of your code? This sounds like it might be a memory issue (alignment or an attempt to access invalid memory.) What kind of code is executing between your setting of the buffer[12] element and your attempt to read it? Is it possible something goes wrong before you get to the read from this array or does your code make it to a printf() placed before the read but not one placed after?

Yeah, I printf my Buffer[12] and then cast it to an integer. after that, I want to printf the integer-value, but nothing happens, the program stops. The code is part of a very big project I'm working on at my University. the Array is fine, the data held inside the array is correct. and the integer is created at the moment the cast is done.

22 Mar 2011

Johannes Sedlmeier wrote:

.. but nothing happens, the program stops ..

If your program is huge and you suspect a cast/compiler issue then you should be able to write a very simple program (like I did) that demos the problem. I susspect the problem is elsewhere and not the cast at all but without either the full picture or a reduced sample of the problem we're not going to get to the bottom of this. My program demos that the cast works just fine. Can you write a similar tiny program that shows it not working?

The fact that you say "the program stops" does point to a memory error of some kind and, as often is the case, the error itself won't be where you think it is.

22 Mar 2011

sounds right to me. maybe i'll give it another try to find possible leaks. for these kind of issues, a debugger for the compiler would be a great advantage. thanks guys.

I'm sorry, but sharing the code would give me some problems with my professors. even parts of it would be difficult, because there are lots of classes that are working together. hoping to find the leakage. now i know, that its not a problem with the cast. Thanks!