3

I always thought, that pointer incrementation/decrementation is operation like this:

 new_ptr=old_ptr+sizeof(type)*count 

So with int * it would be:

  old_ptr=0     //int *ptr=0
  count=1       //int count=1
  new_ptr=old_ptr+sizeof(int)*count = 0+4*1 = 0x0004  //ptr+=count; 

And size of void = 0, so incrementing void_ptr by using += should not change it. But I was probably mistaken. Other thing is ++ operator, which throws error. So if ++ throws error, why does += not throw it too? Example code:

#include <stdio.h>
void tell(const char *s,int *i,void *v){
    printf("%s: \n int_ptr: %#x\n void_ptr: %#x\n",s,i,v);
}
int main(){
    int *int_ptr=0;
    void *void_ptr=0;
    tell("Before",int_ptr,void_ptr);
    int_ptr++;  //int_ptr=int_ptr+sizeof(int); = 0x 0004
    //void_ptr++;   //error: ISO C++ forbids incrementing a pointer of type 'void*'
    tell("After ++",int_ptr,void_ptr);
    int_ptr+=1; //int_ptr=int_ptr+sizeof(int)  =  0x0008
    void_ptr+=1;//void_ptr=void_ptr+sizeof(void)    WHY DOES THIS WORK AND ++ DOES NOT?!     = 0x0001 ?! should be 0x0000, because sizeof void = 0
    tell("After +=",int_ptr,void_ptr); //RESULT: void_ptr=0x1, so does that mean, that sizeof void is 1 and it is not 0
    return 0;
}

Output:

Before:
 int_ptr: 0
 void_ptr: 0
After ++:
 int_ptr: 0x4
 void_ptr: 0
After +=:
 int_ptr: 0x8
 void_ptr: 0x1

Could someone explain me it?

2 Answers2

5

Arithmetic on void pointers is illegal in both C and C++. Some compilers have extensions that will allow it.

In this case GCC has a pointer arithmetic extension that allows arithmetic on void pointers and function pointers, both of which are illegal by the standard. It treats both as if it they point to a type with a size of 1.

Basically it's a compatibility hack that you should avoid in new code.

Why the ++ operator throws an error, when += does not, I'm not sure. ++ used to work in GCC with this extension. Perhaps a bug in this version of GCC, or an inconsistent application of the extension to C++.

Gerald
  • 23,011
  • 10
  • 73
  • 102
  • 1
    Can you explain why it is not legal in the standard? It seems perfectly logical to take it as a type with a size of 1, just for the sake of adding/subtracting without casting it to a different type first. – Codecat Oct 04 '13 at 14:40
  • 1
    @Angelo Geels Because anytime you implicitly change a behavior that is otherwise well defined - such as arithmetic on pointers using the size of the object being pointed to - you get hard to find bugs. void is not an object type, and has no size, therefore treating it as if it has a size of 1, which it does not, is not logical, it is merely convenient in some cases. Explicitly casting to a type that has a size of 1 makes the intent clear, and is not difficult or especially tedious. – Gerald Oct 04 '13 at 14:44
0

So if ++ throws error, why does += not throw it too?

Why the GCC behaviour differs, is, IMHO, a result of a simple human error: at a certain place on the GCC source the macro TYPE_PTROB_P is used, whereas it probably should have been TYPE_PTROBV_P.

chill
  • 16,470
  • 2
  • 40
  • 44