2

Sorry if this seems like a basic question. I've been studying for a midterm I have coming up and I can't seem to wrap my head around this. I understand that argv can be used in the command line when you need to send it arguments, but none of the answers my professor gave us seems to make sense.

The parameter argv in the function main(int argc, char *argv[]) is:
A. An array of characters
B. A string
C. An array of pointers to character
D. A character pointer
E. None of the above

I feel like it is none of the above, but it could be because I don't fully understand the concept of argv. Any help would be appreciated!

22
  • 5
    an array of character pointers. ..so C Commented Nov 22, 2017 at 18:51
  • You are right. Consider that char** argv is another way to think about it. If char* is an array of characters (a string), then what is char**? Commented Nov 22, 2017 at 18:52
  • @coderredoc: I interpreted it to mean "array of pointers to character" singular. As in, pointers to only one character. Which could never be the case (unless you can pass an empty command line argument) Commented Nov 22, 2017 at 18:53
  • 1
    @AndyG The syntax char *ptr doesn't distinguish between a pointer to one or a pointer to many. It's just a pointer to char. Commented Nov 22, 2017 at 18:56
  • 1
    @NickK E is indeed correct, because argv is a pointer to a pointer to a character, which is none of the above. We cannot however know whether you've understood properly and you should ask your professor if you don't understand the concept. Commented Nov 22, 2017 at 19:12

2 Answers 2

5

The correct answer is E, none of the above. Although the parameter declaration looks like an array of pointer to char, the rules of C adjust it to pointer to pointer to char, and so do the rules of C++.

Either your instructor mistakenly intended choice C or your instructor designed a question inappropriately tricky for an introductory class, unless it is extra credit.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks a lot Eric! This is exactly what I was looking for!
"Either your instructor mistakenly intended C" -- On first reading, I thought you mean that the instructor meant to ask about C rather than C++. I now realize that you meant choice C. I'll edit.
The citation is C11 Standard -5.1.2.2.1 Program startup (draft n1570) and this is an evil question. argv is an array of pointers to char, but when passed as a parameter to the function main the first level of indirection is converted to a pointer providing a pointer to pointer to char in main(). So it really is two distinct questions "What is it?" or "What is its resulting type in main() after being passed as a parameter?" question.
@DavidC.Rankin I don't get your point, standard only say "the array members argv[0]", this make me feel strange because standard shouldn't say that argv is an array. More, I don't think that C standard want to force an implementation to use an array for argv. Or maybe all my life is a lie, I don't know.
The standard says "the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings".
|
2

I think your professor wants C, even though the pedanticly correct answer is E. The data referred to by argv is an array, but the variable itself is a pointer. I think it's worth exploring why, because it has nothing to do with the type of array or main.

Consider an array of integers,

int a[] = { 1, 2, 3 }; 

This allocates 3 adjacent integers. The size of the array is sizeof(int) * 3.

Now let's write a function to double the values of each member,

void F( int m[], size_t n ) { for( int i=0; i < n; i++ ) { m[i] *= 2; } int main( int argc, char *argv[] ) { F(a, sizeof(a)/sizeof(a[0])); return EXIT_SUCCESS; } 

What is m? It's declared to be an array, but it's really a pointer: sizeof(m) == sizeof(int*). That's because C doesn't pass arrays as function arguments. The term of art in C is that an array argument decays to a pointer.

It sorta kinda doesn't matter, because C syntax hides a host of sins, er, differences. You can use the subscript notation with both arrays and pointers. For that reason, our function F can treat m almost like an array, except that it requires the length, because it can't derive the length from the size, because the size is the size of the pointer.

Let me say that a different way. When F is called, the "arguments on the stack" are not the values of a, namely 1, 2, and 3. There is just one such argument, a pointer to the first element of a (often thought of as the address of the first element). You can use that pointer as an array partly because the name of an array also refers to the address of the first element.

Now let's back up to your friend argv. Array, or pointer? Let's say your program foo is invoked on the command line:

$ foo sam I am 

What does the operating system do? Somehow, it has to pass those 4 strings (character arrays) to your program. Somewhere, it has to allocate contiguous space for them. Conceptually, the shell might do something like:

char **args = calloc(5, sizeof(char*)); args[0] = "foo"; args[1] = "sam"; args[2] = "I"; args[3] = "am"; 

or,

char args[5] = { "foo", "sam", "I", "am" }; 

Either way, it could pass args to execv(3), invoking your main, and passing you a ... pointer. After all, it can't pass you an array, right?

Please note args must be an array. If it weren't argv[1] would be meaningless.

(Why 5 elements, you ask, when there are only 4 arguments? There's a rule -- C or Posix, i don't remember -- that the last element in the array (!) must be a NULL pointer.)

Array or pointer? Wave or particle? Where you stand depends on where you sit. argv is pointer a to char*, certainly. By definition, though, it's a pointer to the start of an array of char*.

5 Comments

You confuse array and pointer in a question that ask about this difference ;). "The data referred to by argv is an array," wrong, "Please note args must be an array.", wrong. That remind me some funny mail, lkml.org/lkml/2015/9/3/428. "By definition, though, it's a pointer to the start of an array of char*", nope
I'm not confused. I described how an array is passed as a pointer. While exec(3) is free to construct an array of pointers for argv, or accept such an array and pass it verbatim (or copy it) the fact remains that argv points to the start of an array, else the locations up to argv[argc-1] wouldn't be valid. If you think that's not so, you haven't offered any evidence.
First exec() family are not a part of C standard. "argv points to the start of an array, else the locations up to argv[argc-1] wouldn't be valid.", You confuse a pointer that contain the address of contigus numbers of element type and an array. An array is only with the syntax "[5](fixed size) or [n](VLA) or [](automatic size at compilation time only if initialized)", char **args; is not an array, char *argv[]; is not an array, char *args[5] is not an array but a pointer to an array of size 5. int *p = (int [3]){1, 2, 3}; is a pointer. port70.net/~nsz/c/c11/n1570.html#6.2.5p20
"char *args[5] is not an array but a pointer to an array of size 5". Really? What is sizeof(args) in that case? If the answer surprises you, I can only refer you to K&R. I'm sorry if "points to the start of an array" is unclear; to me your description is less clear because redundant, but equivalent.
Oh yeah, my bad char *argv[5]; is an array of size 5 of pointer. I confuse with char (*argv)[5]; Whatever, char *argv[]; is not an array. Array and pointer are not equivalent. Sorry, I'm not a good english speaker, so I can't explain it very well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.