Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does adding to a pointer with += work, but pointer + 1 doesn't?

I am allocating memory for an array, but I am moving where the pointer points forward a little. Accessing the elements works fine. It started to produce a problem with freeing the allocated memory though. Malloc complains that the pointer being freed was never allocated. The problem can reproduced with this simplified code:

int *pointer = malloc(sizeof(int)) + 1;
free(pointer - 1);

I started experimenting, and found this slight variation of the code to work.

int *pointer = malloc(sizeof(int));
pointer += 1;
free(pointer - 1);

What is the += doing different than just adding 1 to the pointer malloc returns in one line?

like image 900
Znapi Avatar asked Jan 31 '15 20:01

Znapi


People also ask

Why pointer addition is not possible?

Pointers contain addresses. Adding two addresses makes no sense because there is no idea what it would point to. Subtracting two addresses lets you compute the offset between the two addresses.

What happens when you add a value to a pointer?

You can only add or subtract integers to pointers. When you add (or subtract) an integer (say n) to a pointer, you are not actually adding (or subtracting) n bytes to the pointer value. You are actually adding (or subtracting) n-times the size of the data type of the variable being pointed bytes.

What happens when you add a pointer to an integer?

Pointer arithmetic and arrays. Add an integer to a pointer or subtract an integer from a pointer. The effect of p+n where p is a pointer and n is an integer is to compute the address equal to p plus n times the size of whatever p points to (this is why int * pointers and char * pointers aren't the same).

Can you add two pointers together?

Adding two pointers is illegal in c program but pointer and integer addition is legal. subtraction of two pointers is also legal. multiplication & division of two pointers are also illegal.


2 Answers

The return type of malloc is void *, which, according to the standard, cannot be used for pointer arithmetic.

There is a GNU extension, however, that treats sizeof(void) as 1 and that is why your first fragment compiles. Later on, pointer - 1 subtracts sizeof(int) and not 1, hence the pointer mismatch.

The actual offsets applied when doing pointer arithmetic always depend on the type of the pointer. Since pointer is an int *, the actual offsets will be multiplied by sizeof(int). If sizeof(void) is 1 or if it's a char * pointer (sizeof(char) == 1), no multiplication takes place.

like image 176
Blagovest Buyukliev Avatar answered Oct 28 '22 15:10

Blagovest Buyukliev


Pointer arithmetic can be done using either of + or +=. It has nothing to do with the error produced.

malloc returns void * type. C standard says that:

C11: 6.2.5 Types (p19):

The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

6.5.6 Additive operators (p2):

For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)

void * is pointer to incomplete type. Therefore, no addition will be performed with void * type. That's why

int *pointer = malloc(sizeof(int)) + 1;  

is wrong and will lead to run time error on executing free(pointer - 1);.

like image 32
haccks Avatar answered Oct 28 '22 14:10

haccks