I don’t understand how it works under the hood. How can C determine how much memory to allocate for argv when the program doesn’t know the number of arguments until it is running?
I tried understanding how C can figure out how much memory to allocate for argv[], since the program doesn’t know how many arguments will be passed until it's actually running. I asked GPT but i didn't really like its answer
I don’t understand how it works under the hood. How can C determine how much memory to allocate for argv when the program doesn’t know the number of arguments until it is running?
I tried understanding how C can figure out how much memory to allocate for argv[], since the program doesn’t know how many arguments will be passed until it's actually running. I asked GPT but i didn't really like its answer
Share Improve this question asked Mar 31 at 23:25 Ignacio Dias GundinIgnacio Dias Gundin 173 bronze badges New contributor Ignacio Dias Gundin is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 5 |3 Answers
Reset to default 4How can
argv
in C be an array if its size is determined dynamically?
Parameter char *argv[]
is not an array even though it has a []
. argv
is a pointer to the first element of an array of pointers. The first array elements point to strings. The last one is equal to NULL
.
How can C determine how much memory to allocate for
argv
when the program doesn’t know the number of arguments until it is running?
The memory is allocated before the program is called. The calling code (e.g. the operating system's command line processor) has determined the memory allocation. How it does that is not specified by C.
I asked GPT but i didn't really like its answer
Not really surprising.
C does not do that... There is no memory allocation at program loading. No size to figure out...
When the program is loaded the operating system allocates memory for the arguments and passes a null-terminated series of pointers to them to the program. And another block of pointers pointing to the environment variables.
The program gets argc
a simple counter with the number of pointers, them the address of the pointer to the 1st argument. A NULL
is passed to signal the end of the arguments, so it is not even needed to know the argument count, as noted by @ikegami.
The C runtime library is responsible for setting the value of argc
and argv
appropriately before calling the function main
. This means that an array will have to be created whose char *
members point to individual strings. The number of strings and the length of these strings are both variable.
Depending on the operating system used, the runtime library may have to allocate the memory for storing the strings, in addition to allocating the memory for the array of pointers to these strings.
In many cases, the runtime library is itself programmed in C, and it will likely have access to the function malloc
or similar function.
The function malloc
can be used for creating an array of variable length of elements of type char *
. This function can also be used for allocating the memory necessary for storing the strings, where each string also has a variable length.
In my example program below, I am using the function malloc
for creating an array of variable length similar to argv
, where each element of the array is a char *
to a string, which is also of variable length. After this array has been created, its content is printed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
int desired_size;
char **arr;
int c;
// read number of strings from user
printf( "Number of strings: " );
if ( scanf( "%d", &desired_size ) != 1 || desired_size < 0 )
{
printf( "Error reading input!" );
exit( EXIT_FAILURE );
}
// discard the remainder of the line
while ( ( c = getchar() ) != '\n' && c != EOF )
;
// allocate memory for array with room for an additional
// NULL pointer to mark the end
arr = malloc( ( desired_size + 1 ) * sizeof arr[0] );
if ( arr == NULL )
{
printf( "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
// fill array with pointers to strings
for ( int i = 0; i < desired_size; i++ )
{
char input[200];
// prompt user for input
printf( "Please enter string #%d: ", i + 1 );
// read input from user
if ( fgets( input, sizeof input, stdin ) == NULL )
{
printf( "Input error!\n" );
exit( EXIT_FAILURE );
}
// remove newline character from input, if it exists
input[strcspn(input,"\n")] = '\0';
// allocate memory for new string
arr[i] = malloc( strlen(input) + 1 );
if ( arr[i] == NULL )
{
printf( "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
// copy the input string to the newly allocated memory
strcpy( arr[i], input );
}
// write a NULL pointer to the end of the array, because
// argv also has a NULL pointer at the end
arr[desired_size] = NULL;
// print the content of the array
printf( "\nThe array has the following content:\n" );
for ( char **p = arr; *p != NULL; p++ )
{
printf( "%s\n", *p );
}
// free the strings
for ( char **p = arr; *p != NULL; p++ )
{
free( *p );
}
// free the main array
free( arr );
}
This program has the following behavior:
Number of strings: 5
Please enter string #1: apple
Please enter string #2: banana
Please enter string #3: cherry
Please enter string #4: dragonfruit
Please enter string #5: elderberry
The array has the following content:
apple
banana
cherry
dragonfruit
elderberry
Side note: In the program above, I am using the function scanf
to read an integer from the user. I am doing this for simplicity. However, it is worth noting that using scanf
is generally not advisable for line-based user input. See this answer of mine to another question on why this is not advisable, and which better alternatives are available.
char *argv[]
passed tomain()
, the memory is allocated before the C program runs, and it is also passedargc
the number of arguments. So C does not need to figure out how much memory was needed. – Weather Vane Commented Mar 31 at 23:42int main(int argc, char *argv[]){...
? But that[]
has not the same meaning in a parameter declaration than in a variable declaration. I am not a c-spec lawyer, but in my book, if it were an array, thensizeof(argv)
would depend on the number of arguments. But it is just the size of a pointer. So, imho, it is just a pointer, as far as the calledmain
is concerned (maybe it was a pointer in the code of whoever filled that memory, but that wasn't even in the C code) – chrslg Commented Mar 31 at 23:48int main(int argc, char *argv[]){ char *argv2[]={"one", "two", "three", NULL}; printf("%ld %ld\n", sizeof(argv), sizeof(argv2));}
, and call your program with 3 arguments. On my machine it prints 8 and 24 (size of a pointer, and size of an array of 4 pointers). Soargv
is a pointer.argv2
is an array in this example. – chrslg Commented Mar 31 at 23:50argv
isNULL
-terminated. So there's not one but two ways of determining the number of elements inargv
. – ikegami Commented Apr 1 at 0:05