1

I am trying to use pointer arithmetic to access pointer locations like an array. For testing same I wrote below code.

Now, I can see that pointer arithmetic is working because I can see incremented pointer address getting printed. But when I am de-referencing that pointer location to set some value then it is not working.

With my knowledge on C and pointers till now, I am not able to reason why pointer de-referencing is not working. If I was not able to get the increased the pointer location/address then atleast I would have understood that pointer arithmetic is not working, but when it is working then why pointer de-referencing is not working.

Code:

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

int **DoublePtr;

void doublePointerTest();

int main(void)
{
    doublePointerTest();
}

void doublePointerTest()
{
    DoublePtr = malloc(sizeof(int*));
    *DoublePtr = malloc(sizeof(int) * 10);

    printf("Address of DoublePtr = %p\n", DoublePtr);
    printf("Address of *DoublePtr = %p\n", *DoublePtr);

    **DoublePtr = 100;

    *DoublePtr += 1;
    printf("+1 Address of *DoublePtr = %p\n", *DoublePtr);
    **DoublePtr = 1;

    *(*DoublePtr += 1) = 2;
    printf("+2 Address of *DoublePtr = %p\n", *DoublePtr);
    //**DoublePtr = 2;

    *DoublePtr += 1;
    printf("+3 Address of *DoublePtr = %p\n", *DoublePtr);
    **DoublePtr = 3;

   // *DoublePtr[4] = 4;
   // *DoublePtr[8] = 8;
   // *DoublePtr[3] = 3;
   // *DoublePtr[2] = 2;

    for(int i = 0; i < 10; i++, *DoublePtr += 1)
    {
        printf("%d.  ", i);
        printf("%d\n", **DoublePtr);
    }
}

O/P:

jharvard@appliance (~/psets/pset5/pset5_working): clang testing.c -o testing
jharvard@appliance (~/psets/pset5/pset5_working): ./testing 
Address of DoublePtr = 0x8cd4008
Address of *DoublePtr = 0x8cd4018
+1 Address of *DoublePtr = 0x8cd401c
+2 Address of *DoublePtr = 0x8cd4020
+3 Address of *DoublePtr = 0x8cd4024
0.  3
1.  0
2.  0
3.  0
4.  0
5.  0
6.  0
7.  0
8.  135105
9.  0
jharvard@appliance (~/psets/pset5/pset5_working):


Updates:

As per comments and answer, corrected my code from DoublePtr = malloc(sizeof(int)); to DoublePtr = malloc(sizeof(int*)); and tested but it gives same result.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
hagrawal7777
  • 14,103
  • 5
  • 40
  • 70
  • @AlterMann Testing, but same result. – hagrawal7777 Feb 18 '16 at 22:02
  • In the printf statements, "Address of" should say "Value of". You are printing the address of the object being pointed to, not the address of the pointer. – M.M Feb 18 '16 at 22:07
  • The commented-out lines `*DoublePtr[4]` would also be a buffer overflow, you probably meant `(*DoublePtr)[4]` – M.M Feb 18 '16 at 22:09

3 Answers3

3

In your code,

 DoublePtr = malloc(sizeof(int));

is wrong. You'll end up allocating wrong amount of memory there. You need to change it to

 DoublePtr = malloc(sizeof(int*));

or, for better,

DoublePtr = malloc(sizeof *DoublePtr );

Also, always check the return value of malloc() to ensure success before using the returned pointer.

That said, another problem is, you kind of ignored the side-effect of using +=. It actually modifies the content of the left operand. So, your *DoublePtr is increased every time you use += on it.

After that, without re-setting it to the original start pointer, you kept on doing += on it in the later loop. This causes two-folded issue

  1. As malloc() returns uninitialized memory, in the loop, you're trying to read all uninitialized memory, which invokes undefined behavior.
  2. As you've not reset the pointer, after the 6th iteration, you're actually going out of bounds, which again invokes UB.
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Testing, but same result. – hagrawal7777 Feb 18 '16 at 22:02
  • "*So, your *DoublePtr is increased every time you use += on it.*" This is what I am trying to do, that's the way I want to access a pointer just like an array by using pointer arithmetic .. @M. M has given right direction .. – hagrawal7777 Feb 18 '16 at 22:19
  • @hagrawal did you miss the _re-setting_ part? That's the cause of your problem. – Sourav Ghosh Feb 18 '16 at 22:21
  • Means ?? Going out of bounds is definitely bad and I will correct it but my problem is that my loop is not starting from beginning but address left in pointer after 3 pointer increment .. I tried to use a temp pointer to hold the original double address `*DoublePtr = malloc(sizeof(int) * 10); int **tempDoublePtr = DoublePtr;` and then use `tempDoublePtr` in FOR loop but no help .. – hagrawal7777 Feb 18 '16 at 22:24
  • Thanks buddy for your valuable inputs. +1 but cannot accept because @M. M has nailed it till last brick. – hagrawal7777 Feb 18 '16 at 22:29
  • 1
    @hagrawal Sure, no issues. Cheers!! – Sourav Ghosh Feb 18 '16 at 22:30
  • I know your allocating memory for int pointer was 110% right but an interesting thing is that after the fix if I revert back to `DoublePtr = malloc(sizeof(int));` then also my code is working as expected .. Probably because int and a pointer, both are of 4 bytes (*I am running code on a 32 bit box*) .. – hagrawal7777 Feb 18 '16 at 22:39
3

Your code writes 100,1,2,3 to the first 4 locations of the 10 you malloc.

Then you print out the contents of the next 10 locations starting from the 3: you see the 3, then 6 uninitialized values, and then a buffer overflow.

You never print the values of the first 3 locations. Your dereferencing to set the value is working but you never output the result.

Perhaps you meant to set *DoublePtr back to its original value before printing?

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Thanks for your inputs buddy, you nailed pretty much but I am still not getting expected o/p .. I used a temp variable to store double pointer address `int **tempDoublePtr = DoublePtr;` and then used this `tempDoublePtr` in FOR loop but still not working, did I do anything wrong? – hagrawal7777 Feb 18 '16 at 22:15
  • @hagrawal Yes, you should have used `int *tempPtr = *DoublePtr;` and then used `tempPtr` in the loop. Saving `DoublePtr` is no use as `DoublePtr`'s value has not changed; it is `*DoublePtr` that changed. Actually it would be better to leave `*DoublePtr` unchanged and use `tempPtr` whenever you want to have a movable pointer. – M.M Feb 18 '16 at 22:23
  • You nailed it mate, you really nailed it. Thanks a lot. – hagrawal7777 Feb 18 '16 at 22:28
1

I can see an issue here at a quick glance. Why are you allocating the double pointer? You should allocate a pointer and then point the double pointer to it or pass the memory address of the allocation to the double pointer.

int* pointer = malloc(sizeof(int) * 10);
int** DoublePtr = &pointer;

OR

int DoublePtr = &malloc(sizeof(int) * 10);

I would recommend using the first method as it is more standard and easier to see what is going on.

Careful Now
  • 260
  • 1
  • 9