-1

I've always dealt with unsigned numbers but for some weird reason they're not working in this code.

Here is the function I have

string compare (unsigned char H[4])
{
unsigned int sum = H[3] + H[2] * 0x100 + H[1] * 0x100 * 0x100 + H[0] * 0x100 * 0x100 * 0x100;
switch(sum)
    {
    case 0x414b4220: return "akb"; break;
    case 0x89425446: return "png"; break;
    case 0xefbbbf3c: return "plist"; break;
    case 0x4c574600:
    case 0x5df90000: return "lwf"; break;
    case 0x4a4d5000:
    case 0x424d4900:
    case 0x434c5300:
    case 0x43485000:
    case 0x53544700:
    case 0x4d415000: return "bin"; break;
    default: return "";
    }

}

The function is being called this way:

unsigned char C[4];
fin2>>C[0]>>C[1]>>C[2]>>C[3];
string ext = compare(C);

The output I'm getting for the value of sum is always 0x89425446, however the value return is always "". So where am I going wrong?

Note: Sometimes the output I get is 0x80000000

user3025371
  • 37
  • 1
  • 5
  • 1
    What does the debugger tell you when you step through the code? – Ken White Jan 19 '17 at 02:54
  • @KenWhite I'm not running the debugger, I'm using CodeBlocks IDE with minimal settings. – user3025371 Jan 19 '17 at 02:57
  • What are the values of `C[0..3]`? Are you sure they are being read correctly? Oh, and I'd use `(unsigned int) H[2] << 8`, etc, rather than multiplying by `0x100`. – Ken Y-N Jan 19 '17 at 03:02
  • Then insert some printf() calls or something to see what your code is actually doing. You expect *us* to debug it for you? We don't have code showing what values you're passing to the function, for one. – Ken White Jan 19 '17 at 03:05
  • @KenY-N The values are read correctly I'm sure of that (the output of them gives 89 42 54 46). Can you explain the Shift 8 more? – user3025371 Jan 19 '17 at 03:05
  • @KenWhite I create my own printf debugging mechanisms that's how I said the value of sum is always 0x89425446. It is what I produce. – user3025371 Jan 19 '17 at 03:06
  • 2
    It clearly is not, or your code wouldn't return the value you're getting back. It would never hit the `default` portion of the switch. Saying *I swear my code is right, but it produces the wrong results. Why?* is simply ludicrous. If it's not switching correctly on the value when your code is written correctly, then the value isn't what you expect. – Ken White Jan 19 '17 at 03:07
  • `89` decimal or `89` hex? For your question, `<< 8` is basically equivalent to `* 0x100`, `<< 16` to `* 0x100 * 0x100`, etc, and is also the form that most people expect to see. – Ken Y-N Jan 19 '17 at 03:13
  • @KenY-N Thanks I will try that now. – user3025371 Jan 19 '17 at 03:19
  • @KenWhite I gave you my exact output! I told you the issue is with the FREAKING SIGN! Instead of getting 0x100 for example I get 0xfffff100. THAT IS THE WHOLE FREAKING ISSUE. – user3025371 Jan 19 '17 at 03:20
  • 3
    Do you think SHOUTING AT ME is going to help? I can't tell you why yo u're getting what you're getting, because **I can't see what you're passing into the function before all of your calculations**. If we can't see what you're passing in, we can't test how `sum` is being calculated incorrectly. It's not my fault you've chosen to use an IDE that doesn't have basic functionality, either. Don't take it out on me because you can't do basic debugging on your own. I'm done here. I don't need the attitude and rudeness. Good luck. – Ken White Jan 19 '17 at 03:25
  • Personal insults are not acceptable here, and doing so can get your account suspended or banned. Be polite, and not insulting. See the [help] regarding the acceptable behavior here, and adhere to those rules. I didn't insult you personally, and I'd expect the same courtesy in return. I didn't once call you a name or insult your intelligence. Again, **be polite** or feel free to find a different site. – Ken White Jan 19 '17 at 03:41
  • 1
    @KenWhite Okay so you actually replied to me in a polite manner after all those insults. You sir deserve my sincere apologies and you have my ultimate respect. Oh BTW I did solve it using the method Ken Y-N provided. I gave sum an initial value of 0, then I ORed it with the left most value, shifted by 8, then ORed it with the next value and so on. – user3025371 Jan 19 '17 at 03:51

1 Answers1

4

I have figured out the problem, I hope:

H[0] * 0x100 * 0x100 * 0x100

(Let us assume 32-bit integers)

According to this answer, 0x100 is actually a signed constant. Furthermore, according to implicit integer promotion rules:

unsigned char or unsigned short can be converted to int if it can hold its entire value range, and unsigned int otherwise;

Thus, the H[0] will be converted to a signed int, so the whole expression is signed, so an H[0] of 0x89 will result in an attempt to get a value of (signed int) (0x89000000), or in other words you will have an integer overflow, undefined behaviour, which in your case gives you an unexpectedly negative value.

As I mentioned in my comments, the canonical way of converting four unsigned bytes to an unsigned integer is:

unsigned int sum = (unsigned int) H[3]
                | ((unsigned int) H[2] << 8)
                | ((unsigned int) H[1] << 16)
                | ((unsigned int) H[0] << 24);

This explicitly promotes H[] to unsigned int, and using a << shift avoids problems of unexpected sign conversions.

PS: Please do not be rude to fellow users - I almost deleted this answer when I saw your comment.

Community
  • 1
  • 1
Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
  • This is the solution I eventually did, I followed what you said in the comments and came up with a similar output. I thought a bit about it too, and I realized that I'm dealing with a character and storing into an integer, so there must've been somewhere where the character was being extended. – user3025371 Jan 19 '17 at 04:24