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 :
- 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] );
}
}
- 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;
}
}
- 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
-
When we do a
malloc( )
,calloc( )
orrealloc( )
, 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 ; inlibc
, that control structure can be a simplesize_t
(depending on certain configuration options inlibc
itself). Your function, assuming your implementation uses asize_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 🙂