GNZ
GNZ

Reputation: 595

Some basic questions about pointers in C and pointer size

In below C code using this online compiler, when I increase the pointer address by one, the actual address increases by four. It is because the data type is int.

#include <stdio.h>

int main()
{
    int my_array[3] = {0, 1, 2};
    int* p_array = my_array;
    
    printf("%p \n", p_array);
    
    p_array = ++p_array;
    
    printf("%p \n", p_array);

    return 0;
}

Output after compilation:

0x7ffeb9ba5814 
0x7ffeb9ba5818

I have two questions:

  1. Is it possible to directly access/point to the single byte at the address 0x7ffeb9ba5815 using pointer? (not by using bitwise operations)

  2. How come the addresses pointers hold in the above case are 6-byte such as 0x7ffeb9ba5818? (I though addresses are either 4 or 8 bytes)

Upvotes: 1

Views: 139

Answers (4)

user16719198
user16719198

Reputation:

such as 0x7ffeb9ba5818?

This is 48-bit virtual address region. Just below the middle. Like 491 of 1000.

printf("%p %p %p %p %p %p %p\n",
         0, 1, 16, 255, -1, -1L, (1L<<48)/2-1);

prints:

(nil) 0x1 0x10 0xff 0xffffffff 0xffffffffffffffff 0x7fffffffffff

Not only leading zeroes are suppressed! Also 0 itself.

0x7fffffffffff is 140 TB. Virtual.

With the next paging level (5) you will see even less leading zeroes.

Upvotes: 0

John Bode
John Bode

Reputation: 123558

If you have a pointer to an object of type T, adding 1 to that pointer yields the address of the next object of that type. For example, assume the following declarations:

char *cp  = (char *)  0x8000;
short *sp = (short *) 0x8000;
long *lp  = (long *)  0x8000;

Then the following will all be true:

Address    char           short         long
–––––––    +–––+          +–––+         +–––+
0x8000     |   | cp       |   | sp      |   | lp
           +–––+          + – +         + - +
0x8001     |   | cp + 1   |   |         |   |
           +–––+          +–––+         + - +
0x8002     |   | cp + 2   |   | sp + 1  |   |
           +–––+          + - +         + - +
0x8003     |   | cp + 3   |   |         |   |
           +–––+          +–––+         +–––+
0x8004     |   | cp + 4   |   | sp + 2  |   | lp + 1
           +–––+          + - +         + - +
            ...            ...           ...

Is it possible to directly access/point to the single byte at the address 0x7ffeb9ba5815 using pointer? (not by using bitwise operations)

Yes - cast it to char * or unsigned char *:

unsigned char *ucp = ((unsigned char *) my_array + 1);

How come the addresses pointers hold in the above case are 6-byte such as 0x7ffeb9ba5818? (I though addresses are either 4 or 8 bytes)

The %p conversion specifier just isn't printing any leading 0s - the actual value is 0x00007ffeb9ba5818.

Upvotes: 2

altermetax
altermetax

Reputation: 706

Firstly, I'm assuming you mean ++p_array and not p_array = ++p_array since that's undefined behavior.

  1. Yes, it is. Cast the pointer to type (char*) (or alternatively also (void*) if using GCC) and that pointer will increase and decrease with steps of 1:
int *a = 0;
a++; // a is now 4
char *b = (char*) a;
b++; // b is now 5
  1. They actually are 8 bytes, but the first two bytes are zeros. When printed they get formatted with as few digits as possible, the same way when you write the number 200 you don't write stuff like 0000200.

Upvotes: 4

Konrad Rudolph
Konrad Rudolph

Reputation: 545885

  1. Yes, for example you can cast the address to a pointer-to-char (which in C is a synonym for a byte!) and access that:

    char *cp = (char *) p_array;
    cp++;
    printf("%p\n", (void *) cp);
    
  2. They’re not 6 bytes; printing the addresses just omits leading zeros, same as it would print 123 in decimal, not 0…0000000123. In reality, the value of the pointer in the first case would be 0x00007ffeb9ba5814.

Upvotes: 3

Related Questions