Gates Gates - 29 days ago 6
C Question

Why is a pointer used when using arguments?

Had a question about this '*argv[]'

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>

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

if(argc != 2){
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
return 1;
}

char *input = argv[1];
for(int i = 0; i < strlen(input); i++) {
if( isalpha(input[i]) == 0 ) {
return 1;
}
}


Argc makes sense to me as it is a int variable that contains the number of arguments passed with the command. However why would argv[] need to be a pointer instead of also a variable in and of itself?

Where is the memory provisioned for the arguments, is there a limit? Are there potential 'catches' to using arguments for input instead of fgets?

Answer

argv is a pointer to the first element of an array of char*. C doesn't actually have the ability to pass arrays as arguments, it passes a pointer to the first element of the array instead.

As for the memory, typically, the arguments are actually stored as a single contiguous block of memory with NULs separating the strings. argv references an array that points to the beginning of each argument, but the pointers aren't independently allocated. If you call a program with:

foo arg1 arg2 arg3

the actual layout in memory would often be something like this:

"foo\0arg1\0arg2\0arg3\0"
 ^0   ^1    ^2    ^3     

where the carets specify where argv entries point:

argv = {&caret0, &caret1, &caret2, &caret3, NULL};

The advantage to this approach is minimal allocator overhead (it can be allocated and freed as a single block, without wasting bytes on alignment or heap tracking data). There is usually a limit on cumulative length of argv or the total number of arguments (OS/compiler dependent); it's large (on the most recent system I checked this on, the total length of the strings was limited to around 128KB), but you could hit it if you use a broad glob on a large tree of files.

The main hitch is the argument length limits, and the fact that all of the data is parsed/loaded at once, where fgets can use less memory by processing a line at a time, reusing a single (smaller) buffer. But if the length limits aren't a major issue, you could always use xargs to convert what would have been lines of input to stdin into sequential arguments to your program. It's a little odd, but not impossible.

Comments