Am I misunderstanding pointer ref/deref, pointer arithmetic or do leading 0's really make a difference in C's ability to detect equality?

2

I've been trying to understand an error I get with the following code

bytes2bits(p,q,pixels)
u_char *p, *q;
register u_int pixels;
{
  register u_char *r, a;
  register u_long *l;

   ...

switch (*l++) {
    case 0x00000000:    a = 0x00; break;
    case 0x00000001:    a = 0x10; break;
    case 0x00000100:    a = 0x20; break;
    case 0x00000101:    a = 0x30; break;

    case 0x00010000:    a = 0x40; break;
    case 0x00010001:    a = 0x50; break;
    case 0x00010100:    a = 0x60; break;
    case 0x00010101:    a = 0x70; break;

    case 0x01000000:    a = 0x80; break;
    case 0x01000001:    a = 0x90; break;
    case 0x01000100:    a = 0xa0; break;
    case 0x01000101:    a = 0xb0; break;

    case 0x01010000:    a = 0xc0; break;
    case 0x01010001:    a = 0xd0; break;
    case 0x01010100:    a = 0xe0; break;
    case 0x01010101:    a = 0xf0; break;

    default:
      (void) fprintf(stderr,"bytes2bits: bad value %x\n",*--l);
      exit(1);
}

    ......

}

My problem lies in the fact that this block of code exits with the error message

bytes2bits: bad value 1010100

I would've thought that 0x01010100 == 1010100 (Note: the fprintf is using %x as output format, so I am looking at a hexadecimal number. Also, when I test and use a printf with %d output format, I see the value 16843008 (= 16^6 + 16^4 + 16^2), which is the equivalent decimal representation of 0x01010100. The 'bad value' 1010100 output is not affected by the presence of my printf checking statement).

bytes2bits: bad value 1010100

How can I make sense of the fact that the switch statement does not recognize 1010100 as the next to last case (i.e.case 0x01010100: a = 0xe0)?

c
pointers
hex
asked on Stack Overflow Jul 11, 2012 by user1245262 • edited Jul 11, 2012 by AnT

3 Answers

5

The only reasonable guess here is that on your platform the u_long that you analyze with switch is longer than int/unsigned int that you are actually printing.

For example, if u_long is a 64 bit type and int is a 32-bit type, then your *l++ might evaluate to 0xBAADF00D01010100. This obviously will not match the case 0x01010100: label. But when you are doing your printfs with %x specifier, you are only printing the trailing 0x01010100 portion.

Use l prefix in format specifiers (%lx, %ld etc.) to print long values to avoid such confusions in the future (assuming that u_long is based on long).

answered on Stack Overflow Jul 11, 2012 by AnT • edited Jul 11, 2012 by AnT
3

Maybe you are on a platform where the size of u_long is not as expected (e.g. a 64 bit word). So *l may take a value bigger than the 32-bit patterns you are testing, and the "%d" and "%x" format could truncate to 32 bit the actual value. I suggest you to print the sizeof(*l).

answered on Stack Overflow Jul 11, 2012 by Giuseppe Guerrini
0

UPDATE: (hope I got it right this time ;-)

a= (*l &         1) << 4
 | (*l &     0x100) >> 3
 | (*l &   0x10000) >> 10
 | (*l & 0x1000000) >> 17
 ;
if ( *l & 0xfefefefe) {
   fprintf(stderr, "Badstuff: %lx\n", (unsigned long) *l);
   exit(EXIT_FAILURE);
   }
 l++;
answered on Stack Overflow Jul 11, 2012 by wildplasser • edited Jul 11, 2012 by wildplasser

User contributions licensed under CC BY-SA 3.0