12 Replies - 7304 Views - Last Post: 24 December 2011 - 09:26 AM Rate Topic: ***** 1 Votes

#1 konos5  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 32
  • Joined: 09-September 09

Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 05:03 AM

Hi everyone!

I would like a few clarifications regarding the way parameters are stored in argv[]
when a C program is called from the console.

In particular "The C Programming Language" of Dennis M.Ritchie states that argv is a pointer to an array
of pointers and treats it as such. However I've seen numerous examples using the following line:

 main(int argc, char *argv[])



which implies that argv is just an array of pointers.

Which one is the correct case and why is that happening?

Is This A Good Question/Topic? 0
  • +

Replies To: Array of pointers in argv[ ] or pointer to array of pointers?

#2 Karel-Lodewijk  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 857
  • Joined: 17-March 11

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 05:17 AM

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



argv here is not a pointer to an array nor an array of pointers. It is a pointer to a pointer.

What I mean is this declaration is the same as:

int main(int argc, char **argv)



This doesn't mean that conceptually there is no difference.

argv can be used just like an array of pointers. Each pointer pointing to a C-style string.

It can not be used as a pointer to an array, this would mean something like this would yield something usable.

(*argv)[0]



This compiles and actually returns the first character of the first argument (program name). But obviously this is not what you want from argv and there is no way to access for example, the second argument, if you don't treat argv as an array.


In short:

If Dennis M.Ritchie said that argv is a pointer an array, he would be wrong. If he however just declared main as

main(int argc, char **argv)



Then this would not be a mistake, this is a perfectly valid way to declare an array of pointers in C/C++.

Edit: changed semantical difference with conceptual difference as to not to confuse my statements as semantical in the C standard sense and made it more concise after reading Oler1s' post.

This post has been edited by Karel-Lodewijk: 21 December 2011 - 08:40 AM

Was This Post Helpful? 1
  • +
  • -

#3 konos5  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 32
  • Joined: 09-September 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 06:01 AM

Thanks for the quick reply!

Ritchie actually says that argv is ***a pointer to an array of pointers***!
The problem is that it treats it as if it was just an array of pointers.

For example in one of his programs he does the following:

main(int argc, char *argv[])
.
.
.
(*++argv)[0] == '-'


to check if the first argument (notice the prefix) is a hyphen which is perfectly fine if argv is a pointer to an array of pointers. But it's not OK if argv is just an array of pointers.
Was This Post Helpful? 0
  • +
  • -

#4 Karel-Lodewijk  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 857
  • Joined: 17-March 11

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 06:32 AM

Quote

***a pointer to an array of pointers***


If that statement relates to argv, then that would be wrong.

pointer to an array of pointers implies a triple indirection. And argv only has a double indirection.

As for this code:

(*++argv)[0] == '-'



I consider incrementing a pointer as treating it like an array. But off-course it works and it is valid C/C++.

Edit: Changed my post to be more concise. As Oler1s pointed out, some statements weren't quite right.

This post has been edited by Karel-Lodewijk: 21 December 2011 - 08:29 AM

Was This Post Helpful? 1
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5940
  • View blog
  • Posts: 12,866
  • Joined: 16-October 07

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 06:59 AM

View Postkonos5, on 21 December 2011 - 09:01 AM, said:

Ritchie actually says that argv is ***a pointer to an array of pointers***!


Yes, I can see how that would be confusing. It's really just a more basic way of looking at things. If it's not a storage type(char, int, struct foo, etc), then when it's passed to a function, it is a pointer.

e.g.
#include <stdio.h>
#include <stdlib.h>

void foo(int argc, char **argv) {
	while(argc-- > 0) {
		printf("%s\n", *argv++);
	}
	printf("\n");
}

void bar(int argc, void *p) { foo(argc, p); }

int main() {
	char *args[] = { "Alpha", "Bravo", "Charlie" };
	foo(sizeof(args)/sizeof(*args), args);
	bar(sizeof(args)/sizeof(*args), args);
	return 0;
}



Of interest here is bar, which just takes an anonymous pointer. It then calls foo, which expects a typed pointer. Ritchie wouldn't have done this originally, but void* showed up as standard later. Prior, you'd often just see char* that would get cast to other things, so the void* is a little more clear.

The typing in C is more a matter of convenience than enforcement. C programmers like this. Most programmers do not consider C a type safe language and most other languages go out of their way to enforce restrictions. This is what is meant by being able to "shoot yourself in the foot" with C. There are no safety nets, but you can do things without them that you simply can't in other languages.
Was This Post Helpful? 0
  • +
  • -

#6 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 07:40 AM

I see some statements here that aren't quite right.

Arrays and pointers are derived types. You take some type, and you can derive an array of it or a pointer to it. Here are some examples:

int a; // integer
int *ap; // pointer to integer
int **app; // pointer to (pointer to integer)
int b[10]; // array
int (*B)/>[10]; // pointer to array
int *bp; // pointer to int;
int * bp[10]; // the [] binds first, so this is an array of pointer to int



Keep in mind that char ** is not a pointer to an array or anything like. char (*)[10] or something is a pointer to an array. Ask yourself what the fundamental type is. If you have char **, the fundamental type is char *. Is char * an array? No. So char ** is not a pointer to an array.

What's more confusing initially is parameter declarations. You cannot pass arrays directly. Never. You can use the syntax, but you won't have an array. It's a pointer. So the following are equivalent:

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



You can't actually have an array without specifying the size, but in a parameter declaration, it's utterly irrelevant. You don't have an array. You have a pointer.

When passing arrays to functions, there's typically two paths one can take. Again, you can't pass an array. But you can pass a pointer. So either pass a pointer to an array. Or you pass a pointer to the first element in the array, and then pass a count of how many elements there are:

void f(int (*p)[10]);
void f(size_t c, int *p); // tell programmers that p points to first element in array



So here's what int main(int argc, char **argv) is. And this relies on you being told that there is an array.

char **argv points to the first element in an array. You can tell how many there are in the array with argc.

*argv is the first element in the array. It has type char*. Where does this pointer point? It points to a string representing a command line argument. So let's say argc is 10. Then argv points to the first char* in an array of 10 char*. And each char* points to a string.
Was This Post Helpful? 3
  • +
  • -

#7 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 21 December 2011 - 11:13 AM

In Ritchie's defense (as if he needs me to defend him), the statement "argv is a pointer to an array of pointers" was accompanied by an illustration that made his meaning perfectly clear:
Posted Image

He referred to an array as the actual storage area that contains the data, so in that sense "pointer to an array" just meant the address of the beginning of that storage, or as Oler1s stated, the address of the first element of the array.

Or looking at it slightly differently, he was referring to argv's value, not "argv" (the name).
Was This Post Helpful? 1
  • +
  • -

#8 konos5  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 32
  • Joined: 09-September 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 22 December 2011 - 06:57 PM

View PostKarel-Lodewijk, on 21 December 2011 - 02:32 PM, said:

Quote

***a pointer to an array of pointers***


If that statement relates to argv, then that would be wrong.

pointer to an array of pointers implies a triple indirection. And argv only has a double indirection.


That’s exactly my point!
You are partially right though...(please read on to find out exactly what I mean)

Let me provide a more concrete example using a slightly modified illustration as found
on Ritchie's book (thanks to r.stiltskin for providing us with the original).

Posted Image

Assuming we want to find out whether the first character of the first command-line argument is 'h',
we do the following (as in Ritchie's book):

(*++argv)[0] == 'h'


Now, there are 2 possible pathways to explain this:

CASE 1) ***argv is an array of pointers***

In this case argv is incremented by one and points to the second element of the array. After it gets dereferenced, it points to the address of the first letter
of the word 'hello'. In the picture above, dereferencing argv takes us from (2) to the address of the start of 'hello' in (3). By further subscripting it with [0],
the address of the first letter of the string gets dereferenced and we can now -correctly- check for equivalence with letter 'h'. (which
if I remember correctly returns 1 in this case.

CASE 2) ***argv is a pointer to an array of pointers***

Treating argv as a pointer to an array of pointers (as Ritchie suggests) is an entirely different story. The prefix alone should make the pointer
point to an entirely different array (in our case that would be garbage). From what I understand, it simply won't work.

Thus, if argv is not a pointer to an array of pointers but neither an array, then what is it?

I hope you see can clearly see my point by now.

P.S. Thank you all for your time and effort into this.
Was This Post Helpful? 0
  • +
  • -

#9 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 22 December 2011 - 09:40 PM

I'm not really sure what your point is. First you say there are 2 possibilities: either argv is an array of pointers or argv is a pointer to an array of pointers, and you pretty much prove that it is the former (an array of pointers) and that seems to be your point.

But then you say "if argv is not a pointer to an array of pointers but neither an array, then what is it?"

To which I say, the 3rd possibility: it's a pointer to the first element of an array of pointers.


Looking more carefully at Ritchie's book, the sentence you are questioning just seems to be a misstatement. The statement "Since argv is a pointer to an array of pointers, we can manipulate the pointer rather than index the array" is near the middle of page 115 of the 2nd Edition. But in the very next sentence it says "This next variation is based on incrementing argv, which is a pointer to pointer to char..." And shortly before the 'troublesome' statement (directly under the illustration) "The first version of echo treats argv as an array of character pointers." And finally, immediately after the second example of the 'echo' program it says "Since argv is a pointer to the beginning of the array of argument strings..."

We all know what it is. Whether you write char *argv[] or char **argv makes no difference. Obviously there is an array. How that array is actually allocated, and whether or not it actually has a name, I don't know; but I don't have to know -- that's the OS's realm. All I need to know is that it's being passed as an argument to my function (main) so the compiler treats it as char **argv -- pointer to pointer to char. As such, in my code I can use pointer notation or array notation and either way the result is the same.

So why are we worrying about this?

This post has been edited by r.stiltskin: 22 December 2011 - 09:52 PM

Was This Post Helpful? 0
  • +
  • -

#10 konos5  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 32
  • Joined: 09-September 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 23 December 2011 - 09:41 AM

View Postr.stiltskin, on 23 December 2011 - 05:40 AM, said:

I'm not really sure what your point is. First you say there are 2 possibilities: either argv is an array of pointers or argv is a pointer to an array of pointers, and you pretty much prove that it is the former (an array of pointers) and that seems to be your point.

But then you say "if argv is not a pointer to an array of pointers but neither an array, then what is it?"

To which I say, the 3rd possibility: it's a pointer to the first element of an array of pointers.


Well spotted. That's exactly where my confusion lies.

My perception of the problem is that argv represents an array of pointers.
How we choose to treat it is (for now) irrelevant.

However Oler1s stated that:

View PostOler1s, on 21 December 2011 - 03:40 PM, said:

You cannot pass arrays directly. Never. You can use the syntax, but you won't have an array. It's a pointer. So the following are equivalent:
...
...
...


and that's where I was confused.

Reading through your entire post though, I realized -and please correct me if I am wrong here- that all Ritchie was trying to say was exactly what you and Oler1s already suggested (in a slightly different way):
Argv IS an array of pointers that should be treated AS a pointer to one of the elements of the array (which are again pointers) and NOT AS A POINTER TO AN array of pointers (as that would lead us to the 'paradox' of case 2 in my previous post).

This post has been edited by konos5: 23 December 2011 - 09:43 AM

Was This Post Helpful? 0
  • +
  • -

#11 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 23 December 2011 - 11:53 AM

View Postkonos5, on 23 December 2011 - 11:41 AM, said:

Argv IS an array of pointers that should be treated AS a pointer to one of the elements of the array (which are again pointers) and NOT AS A POINTER TO AN array of pointers (as that would lead us to the 'paradox' of case 2 in my previous post).

Close enough.

Although I think it would be more precise to say:
argv IS a pointer to a pointer which you may treat as an array of pointers because
(1) there actually is an array of pointers beginning at that memory address (placed there by the OS
and
(2) when you use array notation (e.g., argv[i]) that is immediately translated by the compiler into pointer notation, in this case *(argv + i).
Was This Post Helpful? 1
  • +
  • -

#12 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 23 December 2011 - 01:53 PM

> Argv IS an array of pointers

No, it is not. I do not know of any way to say this more bluntly. An array is not a pointer. A pointer is not an array.

Do not overcomplicate the fundamentals.

char a;



What is the type of a? Character.

char *ap;



What is the type of app? Pointer to character.

char **app;



What is the type of app? Pointer to pointer to character. Nowhere do I utter "array".

Accept this, and then try to understand how pointers can be used to work with arrays. Don't equate the two.
Was This Post Helpful? 1
  • +
  • -

#13 konos5  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 32
  • Joined: 09-September 09

Re: Array of pointers in argv[ ] or pointer to array of pointers?

Posted 24 December 2011 - 09:26 AM

View Postr.stiltskin, on 23 December 2011 - 07:53 PM, said:

argv IS a pointer to a pointer which you may treat as an array of pointers because
(1) there actually is an array of pointers beginning at that memory address (placed there by the OS
and
(2) when you use array notation (e.g., argv[i]) that is immediately translated by the compiler into pointer notation, in this case *(argv + i).


Right. I can see your point. I think I understand now.

'Oler1s' you couldn't have been any clearer. Point taken!

Thank you all for your time and...
I wish you a Merry Christmas!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1