c – How to print an array of pointers without knowing its size?

Question:

I'm just starting out with pointers in C, and it's taking a bit longer than expected. I would like to print a pointer that points to a memory area of ​​integers.

In the main program I have the following

int main(int argc, char* argv[]){

    int tamano = 10, i = 0;
    int *x = (int*) calloc(tamano, sizeof(int));

    for(i = 0; i < tamano; i++){
        x[i] = i+1;
    }

    imprimirPuntero(x);

    return 0;
}

And in the procedure I have the following

void imprimirPuntero(int *ptr){
    int i = 0;

    printf("Valores: ");
    for(i = 0; i < 10; i++){
        printf("%d ", ptr[i]);
    }
}

So my question really is… How do I know how many positions the pointer has, without passing that size to it in the procedure?

Answer:

In these cases, you only have 3 real options, plus a 4th bonus :

  1. Pass the size as an argument to the function.

As you indicate, you cannot/want to use this option:

void imprimirPuntero( const int *ptr, size_t sz ) {
  printf( "Valores: " );
  for( size_t i = 0; i < sz; ++i ) {
    printf( "%d ", ptr[i] );
  }
}
  1. Pass a pointer to the function that indicates a known position.

The normal thing is to pass a pointer to the element immediately after the last one. However, nothing prevents you from passing a pointer to, say, the penultimate element (except for making the code a bit more complicated). Your function, passing the position immediately after last, would look like this:

void imprimirPuntero( const int *beg, const int *end ) {
  printf( "Valores: " );
  while( beg != end ) {
    printf( "%d ", *beg );
    ++beg;
  }
}
  1. Mark the end of the array with a specific value.

This is what the compiler does automatically with strings, using a 0 to mark their end. Well, the same, but adapted to the type of data you are using. And, of course, the compiler won't do it for you , you'll have to put that value by hand in the last position.

void imprimirPuntero( const int *beg, int mark ) {
  printf( "Valores: " );
  while( *beg != mark ) {
    printf( "%d ", *beg );
    ++beg;
  }
}

Bonus

  1. When we do a malloc( ) , calloc( ) or realloc( ) , the implementation has its own way of managing memory. Normally, just before the address that is returned to us, some control data is placed, depending on the implementation ; in libc , that control structure can be a simple size_t (depending on certain configuration options in libc itself). Your function, assuming your implementation uses a size_t as the control type:

     void imprimirPuntero( const int *ptr ) { size_t sz = *( ( (size_t *)ptr ) - 1 ); printf( "Valores: " ); for( size_t i = 0; i < sz; ++i ) { printf( "%d ", ptr[i] ); } }

This last option is not 100% reliable; For performance reasons, the library usually allocates more bytes than necessary. But it's good to know that this possibility exists 🙂

Scroll to Top