Question

I'm looking at some code a classmate posted and it has been simplified for the sake of this example:

int main()
{
    int n = 0x4142;
    char * a = (char *) &n;

    char * b1 = (((char *) &n) + 1);
    char * b2 = (((int) &n) + 1);

    printf("B1 Points to 0x%x - B2 Points to 0x%x\n", b1, b2);

    printf("A Info - 0x%x - %c\n", a, *a);
    printf("B1 Info - 0x%x - %c\n", b1, *b1);
    printf("B2 Info - 0x%x - %c\n", b2, *b2);

   return 0;
}

The output is:

B1 Points to 0xcfefb03d - B2 Points to 0xcfefb03d
A Info - 0xcfefb03c - B
B1 Info - 0xcfefb03d - A
Segmentation fault (core dumped)

It segmentation faults when trying to print out b2. Whereas I think the output should include the following line instead of seg faulting:

B2 Info - 0xcfefb03d - A

Why is this the case? b1 and b2 are both char*, and they both point to the same address. This is on a 64bit machine where sizeof(char*) == 8 and sizeof(int) == 4 if that matters.

Was it helpful?

Solution

but it segfaults on a 64bit computer

The likely reason is that, on your platform, pointers are 64-bit and ints are 32-bit. Thus when you cast the pointer to int, you lose information.

My compiler specifically warns about this:

test.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

This is easy to see using the following program:

#include <stdio.h>

int main()
{
   char *s = "";
   printf("%p %p\n", s, (char*)(int)s);
   return 0;
}

On my computer, this prints two different addresses (the second has its top bits chopped off).

what I don't quite understand is that both b1 and b2 are char*, and they both point to the same address

Actually, they don't point to the same address. Your printf() format specifiers are all wrong. The first printf() should be:

printf("B1 Points to %p - B2 Points to %p\n", b1, b2);

When you run this, you'll see that the addresses differ.

OTHER TIPS

(int)&n may truncate the address of n to how many bits there are in int, IOW, if the pointer size is longer than the size of int (which is often the case on 64-bit CPUs), you get a bogus, truncated address/pointer that you cannot dereference safely.

In your example, since an int is 4 bytes, the value of &n is truncated when you cast it and try to assign it to b2. To treat pointer values as integers, use uintptr_t, an unsigned integer type that can safely store a pointer regardless of the platform capacity:

char * b2 = (((int) &n) + 1);

should be:

char * b2 = ((uintptr_t) &n) + 1;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top