Search code examples
cpointersmemory-managementdynamic-memory-allocationdynamic-arrays

Using the address of a pointer as a loop condition in C


I am trying to execute the code below:

#include <stdio.h>

int main()
{
  
    int var1 = 7;
    int* ptr1 = &var1;
    int* ptrHold = ptr1;
    int memo = 0;

    ptr1 = (int*)malloc(7*sizeof(int));

    if(ptr1==NULL){
        printf("Memory couldn't be allocated...");
        exit(0);
    }
    else{
        printf("Memory allocated for ptr1 = %d\n",7*sizeof(int));
        printf("%d",(*(&ptr1+1)-ptr1));

        for(int i=0;memo<=(*(&ptr1+1)-ptr1)/sizeof(int);i++){
        *ptr1=i;
        memo += (int)(sizeof(int));
        ptr1++;
        }
    }

    ptr1 = ptrHold;

    for(int i=0;i<5;i++){
        printf("%d \n",ptr1[i]);
    }

    free(ptr1);
    return 0;
}

But it gives me weird outputs and I think it is because of the loop condition I am using:

memo<=(*(&ptr1+1)-ptr1)/sizeof(int)

I am basically trying to subtract the value of my pointer (address of it) from the next memory location and I will have the memory it takes. After dividing it to the sizeof(int) I thought that I would get the memory allocated to the pointer in bytes and by incrementing the memo variable with the size of int, I would traverse the pointer and assign values to each block.

This individual program has no aim and I know that it is not efficient. I am not trying to create an efficient program, just trying to understand some concepts deeply. I may be making a fundamental mistake, but I am confused and I would like to understand why doesn't this code work.

My expected output was:

Memory allocated for ptr1 = 28
0
1
2
3
4

Solution

  • First, I'll start with some solutions.

    Expressions you could have used if you wanted to keep memo:

    • memo < 7 * sizeof( int )
    • memo < ( &ptrHold[7] - &ptrHold[0] ) * sizeof( int )
    • memo / sizeof( int ) < &ptrHold[7] - &ptrHold[0]

    Expressions you could have used if you wanted to keep ptr1:

    • ptr1 < &( ptrHold[7] )
    • ptr1 < ptrHold + 7
    • ptr1 - ptrHold < 7

    You have:

    memo <= ( *( &ptr1 + 1 ) - ptr1 ) ) / sizeof( int )
    

    You want the loop to end after seven passes, so you want something equivalent to

    memo <= ( 7 - 1 ) * sizeof( int )
    

    There's just no way to always get the constant ( 7 - 1 ) * sizeof( int ) from a varying ptr1. The equation is clearly wrong, and not just superficially so. The whole idea is flawed.


    I am basically trying to subtract the value of my pointer (address of it) from the next memory location and I will have the memory it takes.

    No, you will have 1. Pointer arithmetic works in units of the thing pointed, not in terms of bytes. That's why ptr1++; worked when you used it.

    Let's look at a simple case.

    uint32_t a[2];
    
    int *p = &( a[0] );
    int *q = &( a[1] );
    

    It produces something like the following:

         int *p                  int a[2]
    2000 +-----------+      1000 +-----------+
         | 1000    -------->     |           |
         +-----------+      1004 +-----------+
                        +-->     |           |
                        |        +-----------+
         int *q         |
    3000 +-----------+  |  
         | 1004    -----+
         +-----------+     
    

    The addresses might be 4 bytes apart.

    printf( "%p\n", (void *)p );  // 0x1000
    printf( "%p\n", (void *)q );  // 0x1004
    

    But the differences between the pointers is one.

    printf( "%td\n", p - q );     // 1
    

    It's easy to show that's always the case.

       &( a[1] ) - &( a[0] )               // Two adjacent array elements.
    ≡  &( *( a + 1 ) ) - &( *( a + 0 ) )   // `x[y]` ≡ `*( x + y )` by definition.
    ≡  ( a + 1 ) - ( a + 0 )
    ≡  a + 1 - a - 0
    ≡  1
    

    Similarly, &ptrHold[7] - &ptrHold[0] is equal to 7.