Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer Arithmetic in C [duplicate]

Tags:

c

pointers

I have the following code. Perhaps I have not understood pointer arithmetic as well as I should have but why is int_pointer incremented by 4 instead of by 1? With char_pointer, why isn't it incremented by 4 instead of 1?

 #include <stdio.h>

 int main() {
    int i;

    char char_array[5] = {'a', 'b', 'c', 'd', 'e'};
    int int_array[5] = {1, 2, 3, 4, 5};

    char *char_pointer;
    int *int_pointer;

    char_pointer = int_array; // The char_pointer and int_pointer now
    int_pointer = char_array; // point to incompatible data types.

    for(i=0; i < 5; i++) { // Iterate through the int array with the int_pointer.
        printf("[integer pointer] points to %p, which contains the char '%c'\n",
            int_pointer, *int_pointer);
        int_pointer = int_pointer + 1;
    }

    for(i=0; i < 5; i++) { // Iterate through the char array with the char_pointer.
        printf("[char pointer] points to %p, which contains the integer %d\n",
            char_pointer, *char_pointer);
        char_pointer = char_pointer + 1;
    }
 }

OUTPUT:

[integer pointer] points to 0xbffff810, which contains the char 'a'
[integer pointer] points to 0xbffff814, which contains the char 'e'
[integer pointer] points to 0xbffff818, which contains the char ' '
[integer pointer] points to 0xbffff81c, which contains the char '
[integer pointer] points to 0xbffff820, which contains the char ' '
[char pointer] points to 0xbffff7f0, which contains the integer 1
[char pointer] points to 0xbffff7f1, which contains the integer 0
[char pointer] points to 0xbffff7f2, which contains the integer 0
[char pointer] points to 0xbffff7f3, which contains the integer 0
[char pointer] points to 0xbffff7f4, which contains the integer 2
like image 376
user3754974 Avatar asked Aug 16 '14 01:08

user3754974


2 Answers

That's how pointers aritmetics works: if you increment the pointer by 1, the address gets increased by the size of the pointer type. So since in your machine ints are 4 bytes, incrementing an int pointer increases the address of 4 bytes.

like image 129
Ramy Al Zuhouri Avatar answered Oct 15 '22 12:10

Ramy Al Zuhouri


Undefined Behavior

What you have is undefined behavior, first you are violating the strict aliasing rule which basically makes it illegal to access an object through a pointer of a different type, although access through a char * is allowed. I will quote my answer here which covers this more extensively:

the strict aliasing rules which makes it illegal to access an object through a pointer of a different type, although access through a char * is allowed. The compiler is allowed to assume that pointers of different types do not point to the same memory and optimize accordingly. It also means the code invokes undefined behavior and could really do anything.

Second different pointers may have different alignment requirements and so accessing your char array through an int pointer may very well violate this requirement since the char array may not be aligned properly for an int. The draft C99 standard covers this in section 6.3.2.3 Pointers which says (emphasis mine):

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned57) for the pointed-to type, the behavior is undefined.

A good compiler with the right set of flags should help a lot here, using clang and the following flags -std=c99 -fsanitize=undefined -Wall -Wextra -Wconversion -pedantic I see the following warnings (see it live):

warning: incompatible pointer types assigning to 'char *' from 'int [5]' [-Wincompatible-pointer-types]
char_pointer = int_array; // The char_pointer and int_pointer now
             ^ ~~~~~~~~~

warning: incompatible pointer types assigning to 'int *' from 'char [5]' [-Wincompatible-pointer-types]
int_pointer = char_array; // point to incompatible data types.
            ^ ~~~~~~~~~~

and during runtime I see the following error:

runtime error: load of misaligned address 0x7fff48833df3 for type 'int', which requires 4 byte alignment
0x7fff48833df3: note: pointer points here
00  e0 3e 83 61 62 63 64 65  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  6d 47 60 5a 1d 7f 00
             ^ 

Pointer arithmeic

So pointer arithmetic is based on the size of the type that is being pointed to. How would array access which is basically syntactic sugar for pointer arithmetic work correctly otherwise? You can a read more detailed description here and related discussion here.

like image 45
Shafik Yaghmour Avatar answered Oct 15 '22 11:10

Shafik Yaghmour