Why Does Int Pointer '++' Increment by 4 Rather Than 1

Why does int pointer '++' increment by 4 rather than 1?

When you increment a T*, it moves sizeof(T) bytes. This is because it doesn't make sense to move any other value: if I'm pointing at an int that's 4 bytes in size, for example, what would incrementing less than 4 leave me with? A partial int mixed with some other data: nonsensical.


Consider this in memory:

    [↓      ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]

Which makes more sense when I increment that pointer? This:

            [↓      ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]

Or this:

      [↓      ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]

The last doesn't actually point an any sort of int. (Technically, then, using that pointer is UB.)

If you really want to move one byte, increment a char*: the size of of char is always one:

int i = 0;
int* p = &i;

char* c = (char*)p;
char x = c[1]; // one byte into an int

†A corollary of this is that you cannot increment void*, because void is an incomplete type.

Why a pointer + 1 add 4 actually

Consider what a pointer is... it's a memory address. Every byte in memory has an address. So, if you have an int that's 4 bytes and its address is 1000, 1001 is actually the 2nd byte of that int and 1002 is the third byte and 1003 is the fourth. Since the size of an int might vary from compiler to compiler, it is imperative that when you increment your pointer you don't get the address of some middle point in the int. So, the job of figuring out how many bytes to skip, based on your data type, is handled for you and you can just use whatever value you get and not worry about it.

As Basile Starynkvitch points out, this amount will vary depending on the sizeof property of the data member pointed to. It's very easy to forget that even though addresses are sequential, the pointers of your objects need to take into account the actual memory space required to house those objects.

C pointer arithmetic different for char * and int *

when you declare a variable e.g.

int* a;
char* b;

all offsets are in the end calculated as byte offsets, the size of the offset depends on the type.

so a + 1 is in reality a + sizeof(int) and b + 1 is in reality b + sizeof(char)

the compiler handles this, it makes it easier to read the code otherwise you would always have to calculate how many bytes a type has when looping through an array and such

increment value of int being pointed to by pointer

The ++ has equal precedence with the * and the associativity is right-to-left. See here. It's made even more complex because even though the ++ will be associated with the pointer the increment is applied after the statement's evaluation.

The order things happen is:

  1. Post increment, remember the post-incremented pointer address value as a temporary
  2. Dereference non-incremented pointer address
  3. Apply the incremented pointer address to count, count now points to the next possible memory address for an entity of its type.

You get the warning because you never actually use the dereferenced value at step 2. Like @Sidarth says, you'll need parenthesis to force the order of evaluation:

 (*ptr)++

Why does a pointer increment in nibbles instead of bytes in an array?

As other answers have said, the pointers here are incrementing in bytes, not nibbles.

I believe you're inferring a relationship that doesn't exist between the addresses and the actual chunks of memory.

In a byte-addressable machine, each byte has its own address. You increment by one to get to the next address. So you have the address 0x002BF94C, and the next address is 0x002BF94D. While the change in the addresses only affects the lowest nibble of the address itself, that has nothing to do with the chunk of memory that the address points to. Since this machine is apparently byte-addressable, the number of bits between the chunk addressed by 0x002BF94C and the one addressed by 0x002BF94D is, in fact, 8 bits, or one byte.

The choice of what to use as addresses is arbitrary. The people who designed the architecture could have chosen to give each byte a name, street number, and zip code, but it was obviously more convenient to give them numbers. The choice of what sized chunk of memory gets its own address is also arbitrary. Some machines of the past didn't have byte-addressable memory; they had word-addressable memory, so only groups of 16 or 32 bits (or whatever size the makers wanted) got their own addresses. You could theoretically have a nibble-addressable machine, although I don't think anyone has made one. There is no necessary relation between the address and how much memory it refers to.

The diagram in the question is probably adding to the confusion. Remember that 32 bits is equivalent to 4 bytes, so each 32-bit number has four addresses pointing to its various parts. Each addressed segment in the diagram is a byte; if they were nibbles, the integers would only have two bytes and would be 16-bit, not 32-bit. Since the numbers are in hexadecimal there, each digit represents a nibble, so 01 is actually two nibbles / eight bits / one byte, 0000 0001.

0x002BF94C -> 01  This is one byte
4D -> 00 This is the next byte
4E -> 00 etc.
4F -> 00

If this machine were nibble-addressable, the diagram would look like this:

0x002BF94C -> 1  This is one nibble
4D -> 0 This is the next nibble
4E -> 0 etc.
4F -> 0
50 -> 0
51 -> 0
52 -> 0
53 -> 0


Related Topics



Leave a reply



Submit