0

There're 2 things I don't understand, usually when using malloc() / calloc() we type cast the it because they return a void pointer so we type cast it to our pointer type so we could do pointer arithmetic with it. So I've made a code example where I use malloc() and I don't type cast it and the pointer arithmetic still works :

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p = malloc(8);
    *p++ = 30;
    *p = 40;
    printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
    return 0;
}

why is that ?

Another question of mine regarding to pointers arithmetic is that the code I showed you above, I originally wrote it as follow :

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p = malloc(8);
    *p++ = 30;
    *p-- = 40;
    printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
    return 0;
}

Notice the difference is *p-- = 40. I've use p-- because I wanted to print the correct address the pointer was pointing at, I was assuming that after I use p++ I need to use p-- so the pointer will point at the address of the value of 30, but if I added the p-- and printed it I've noticed that it prints another value. So something here doesn't click for me what's going on with it ? Also if I removed the -- and then printed, it printed 30 and then 40 as I expected BUT the address remained the same, I've expected it to be the previous address+4 which it wasn't yet the value changed, what's going on ?

https://i.stack.imgur.com/A3t6K.jpg

Omlis532
  • 53
  • 2
  • 7

1 Answers1

1

Pointer arithmetic depends on the type with which your pointer is declared. Since your pointer is int *, then ++ and -- will increment and decrement the (raw) value of the pointer by sizeof(int) so that you can access adjacent int values.

In C, it is possible to assign a void * to another type of pointer (such as int *) without triggering a warning (this is not true in C++). In this case the cast is implicitly performed by the compiler.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • I know that pointer arithmetic depends on the type but read what I've tried and what were my results which seems to me weird. About the type casting, so it's done automatically by my compiler (talking about C only) – Omlis532 Sep 19 '14 at 01:04
  • I think most of your confusion arises from the undefined behaviour in your `printf` call as mentioned in the comments. Sort that out, and things will likely make a lot more sense. – Greg Hewgill Sep 19 '14 at 01:05
  • I've added a picture of how I see it, so first we have a pointer pointing at 8 bytes (2 consecutive ints). Our pointers points at our first integer (shown in image #1), in picture 2 we put 30 in our first integer and increment the pointer to point at the second one (shown in image #2), in the last image we put 40 in that address and we decrements the pointer to point back to the original integer. That's what I thought will happen if I do *p++ = 30 and then *p-- = 40 but if I do *p**--** = 40 the printf function prints other value then 30 at the first time and 30 at the second time, – Omlis532 Sep 19 '14 at 01:19
  • from that I understand that it's like after I incremented the pointer in the first time *p++ = 30 and then assigned a value to that address using *p-- = 40, it's like when I assign a value to an incremented pointer the pointer points back to the original address and then the decrements takes place and decrements it to point to not associated address, is it true what I just said ? if we have a pointer that points to our first int then we increment the pointer and assign a value to the second integer the pointer will reset and will point to the original address ? (follow-up of previous comment) – Omlis532 Sep 19 '14 at 01:21
  • I believe your understanding is correct. However, your `printf` statement is giving you misleading answers because if you use `p++` or `p--` in a statement, then you can't use `p` in any other way in that same statement. This is **undefined behaviour**. Fix your `printf` statement before doing anything else. – Greg Hewgill Sep 19 '14 at 01:22
  • so what you're saying is that my assignment *p++ = 30 and then *p-- = 40 is correct but the arguments I give to printf are incorrect ? If I've understood you correctly, could you show me on how should I pass the arguments to the printf function and show me what I did wrong ? – Omlis532 Sep 19 '14 at 01:26
  • I would do something like `printf("The first element is %d and the second is %d; p points to address [%p] and a is [%p]\n", a[0], a[1], p, a);` and change the first line to `int *a = malloc(8);` and add `int *p = a;` after that. If you have a pointer to allocated memory, it's helpful to hang on to the original pointer so that you can free it later with `free(a);` (and not worry about where `p` points at that time). – Greg Hewgill Sep 19 '14 at 01:34
  • I'm understanding my mistake now, because I used arithmetic when passing my pointer to printf it affected the pointer itself since it's passed by ref. What I don't understand is why would you do int *a = malloc(8); and then int *p = a; ? what's the good of it ? – Omlis532 Sep 19 '14 at 01:39
  • I explained why above. It does two things really: (1) it lets you write `free(a)` without worrying about where `p` is pointing, and (2) it lets you compare `p` to `a` to check that you don't decrement past the beginning of the allocated memory. – Greg Hewgill Sep 19 '14 at 01:40
  • if in my example I would do p++; and then free(p) would only the second 4 bytes will be deallocated ? – Omlis532 Sep 19 '14 at 01:43
  • No. You can't do a partial free. You have to free the *entire* block that was originally allocated. – Greg Hewgill Sep 19 '14 at 01:47
  • but If I do what I just described will it actually free only the second 4 bytes ? or will it take into consideration the bytes we skipped – Omlis532 Sep 19 '14 at 01:51
  • At best, if you free a pointer that doesn't point to the start of the allocated block, then you will get a runtime error and your program will crash. At worst, the heap memory will become corrupted and all kinds of things will go wrong later. From the documentation, *"free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc()."* – Greg Hewgill Sep 19 '14 at 01:54