473,387 Members | 1,463 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Understanding char **argv

Hello all,

Forgive the somewhat simple question I am sure this will be, but I am
having some problem understanding what: char **argv looks like. For
instance, i know through trial and error that if I do this:

#include <stdio.h>

int main(int argc, char *argv[])
{
int l;
for( l=0; l<argc; l++ )
{
printf("Pointer: %p\tValue: %s\n", argv++, *argv);
}

return 0;
}

And i invoke the above as:

../foo one two three

Then I will see:
0x10202 foo
0x10204 one
0x10208 two
ox1020c three

Listed, but I would have expected to have needed to write:

*(*(argv))

So as to dereference what the pointer that *argv pointed to. Or have
I missed the point?

Thanks.

Kevin
Jul 5 '08 #1
12 6558
ke************@googlemail.com said:
Hello all,

Forgive the somewhat simple question I am sure this will be, but I am
having some problem understanding what: char **argv looks like.
argv is a pointer to the first element in an array of pointers to char,
where each pointer in the array points to the first character in a string.
For
instance, i know through trial and error that if I do this:

#include <stdio.h>

int main(int argc, char *argv[])
{
int l;
for( l=0; l<argc; l++ )
{
printf("Pointer: %p\tValue: %s\n", argv++, *argv);
Replace that line with these two:

printf("Pointer: %p\tValue: %s\n", (void *)argv, *argv);
++argv;

<snip>
Listed, but I would have expected to have needed to write:

*(*(argv))
That's equivalent to **argv, and each iteration through the loop would give
you the first character of the relevant string for that iteration:

printf("Pointer: %p\tValue: %s\tFirst: %c\n",
(void *)argv,
*argv,
**argv);
++argv;

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jul 5 '08 #2
ke************@googlemail.com wrote:
Hello all,

Forgive the somewhat simple question I am sure this will be, but I am
having some problem understanding what: char **argv looks like. For
instance, i know through trial and error that if I do this:

#include <stdio.h>

int main(int argc, char *argv[])
{
int l;
for( l=0; l<argc; l++ )
{
printf("Pointer: %p\tValue: %s\n", argv++, *argv);
}

return 0;
}

And i invoke the above as:

./foo one two three

Then I will see:
0x10202 foo
0x10204 one
0x10208 two
ox1020c three

Listed, but I would have expected to have needed to write:

*(*(argv))

So as to dereference what the pointer that *argv pointed to. Or have
I missed the point?
Peel the onion one layer at a time.

`argv' is a pointer to a pointer to a char, which I'll
write as "pointer to [pointer to char]" for emphasis.

Applying `*' to a pointer accesses the thing the pointer
points to. So `*argv' is a "[pointer to char]", the thing
that `argv' itself points at.

Now we apply `*' again, this time to the "[pointer to
char]" we got from the first step. `**argv' (which is the
same a `*(*argv))') is therefore a char, the first char of
one of the argument strings.

Another thing you can do to gain facility in understanding
multiple levels of pointers is to draw a picture:

char** char*'s char's

argv ---argv[0] ---{ 'f', 'o', 'o', '\0' }
argv[1] ---{ 'o', 'n', 'e', '\0' }
argv[2] ---{ 't', 'w', 'o', '\0' }
argv[3] ---{ 't', 'h', 'r', 'e', 'e', '\0' }
argv[4] == NULL

--
Eric Sosman
es*****@ieee-dot-org.invalid
Jul 5 '08 #3
ke************@googlemail.com wrote:
Hello all,

Forgive the somewhat simple question I am sure this will be, but I am
having some problem understanding what: char **argv looks like. For
instance, i know through trial and error that if I do this:

#include <stdio.h>

int main(int argc, char *argv[])
{
int l;
for( l=0; l<argc; l++ )
{
printf("Pointer: %p\tValue: %s\n", argv++, *argv);
}

return 0;
}

And i invoke the above as:

./foo one two three

Then I will see:
0x10202 foo
0x10204 one
0x10208 two
ox1020c three

Listed, but I would have expected to have needed to write:

*(*(argv))

So as to dereference what the pointer that *argv pointed to. Or have
I missed the point?
Maybe two points.

1. The parens are not needed. 'char **argv' is what it is, a pointer to
a pointer to char.

2. In your printf statement above you have both argv++ and *argv.
Because we have no way to know which expression might be evaluated
first, this is classic Undefined Behavior.

#include <stdio.h>

int main(int argc, char **argv)
{
int l;
for (l = 0; l < argc; l++) {
printf("Pointer: %p\tValue: %s\n", argv, *argv);
argv++;
}
return 0;
}

...is the way I would do it.
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jul 5 '08 #4
Eric --

On 5 Jul, 22:34, Eric Sosman <esos...@ieee-dot-org.invalidwrote:
char** char*'s char's

argv ---argv[0] ---{ 'f', 'o', 'o', '\0' }
argv[1] ---{ 'o', 'n', 'e', '\0' }
argv[2] ---{ 't', 'w', 'o', '\0' }
argv[3] ---{ 't', 'h', 'r', 'e', 'e', '\0' }
argv[4] == NULL
If *only* one of the books I've been reading had this in it, I
wouldn't be as confused -- thank you very much for that, and to the
others in this thread who've replied.

I suppose understand conceptually how type_t **foo works -- i do have
to ask *why* the command-line options to a program is in the form:

char **foo

As opposed to a singular array of chars, i,e,:

char foo[SOME_MAX_VALUE]

My guess is: char **foo defers the decision to decide how big the
array might be at runtime, but I could be wrong.

Thanks once again for everyone's patience -- I know this is heavy
going.

Kevin
Jul 5 '08 #5
"ke************@googlemail.com" <ke************@googlemail.com>
writes:

<snip>
I suppose understand conceptually how type_t **foo works -- i do have
to ask *why* the command-line options to a program is in the form:

char **foo

As opposed to a singular array of chars, i,e,:

char foo[SOME_MAX_VALUE]

My guess is: char **foo defers the decision to decide how big the
array might be at runtime, but I could be wrong.
I doubt it. The best argument is that it is the "right thing to do".
Imagine your version. Every program would have to decide itself how
to parse the command into parts. A program that operates on files can
just run through the elements of argv doing its job on each one. If
it got one long string, how does it decide what is a file name?

--
Ben.
Jul 5 '08 #6
On Sat, 05 Jul 2008 15:20:11 -0700, ke************@googlemail.com wrote:
I suppose understand conceptually how type_t **foo works -- i do have to
ask *why* the command-line options to a program is in the form:

char **foo

As opposed to a singular array of chars, i,e,:

char foo[SOME_MAX_VALUE]

My guess is: char **foo defers the decision to decide how big the array
might be at runtime, but I could be wrong.
That is two separate questions.

q1) why is it char* and not char[SOME_MAX_VALUE] ?

a1) It allows implementors to only use the minimum required or to use
some maximum value if they prefer. The downside is that the user
programmer cannot rely on being able to write past the end of the string,
but that's not a problem because he can define his own MAX_VALUE and
create his own automatic array if he needs it.

q2) Why is it char** and not char* ?

a2) Because that would greatly limit the power of shells, and it would
require every application to perform its own command line interpreting
(eg: working out that 'some string' is one argument without the quotes).

As an aside, on many implementations there is no specific limit on the
length of any one argument, but the total of all of them is limited.
Here IIRC that limit is 32kiB.

HTH
viza
Jul 5 '08 #7
On 5 Jul, 23:32, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
I doubt it. The best argument is that it is the "right thing to do".
Imagine your version. Every program would have to decide itself how
to parse the command into parts. A program that operates on files can
just run through the elements of argv doing its job on each one. If
it got one long string, how does it decide what is a file name?
But if it were just an array holding type_t:

type_t foo[BAR];

Then BAR could still be evaluated at run-time -- much like argc is to
main() surely? So again: Why the need for multiple indirection -- I
am not saying you're wrong, I am just curious why we have it for
command-line options in this case, and perhaps where other use of:
type_t **foo come into play.

Thanks!

Kevin
Jul 5 '08 #8
ke************@googlemail.com wrote:
So again: Why the need for multiple indirection
[...] I am just curious why we have it for
command-line options in this case [...]
Because there is no "string" type in C.
If C had a string type (which I'll call 'tstring'),
main could probably be declared as

int main(int argc, tstring argv[])

where argv is an array of tstring.

But ... strings in C are represented by char *.

=============
#include <stdio.h>
typedef char * tstring;
int main(int argc, tstring argv[]) {
int n;
for (n=0; n<argc; n++) {
printf("arg %d is \"%s\".\n", n, argv[n]);
}
return 0;
}
Jul 5 '08 #9
ba******@gmail.com said:
ke************@googlemail.com wrote:
>So again: Why the need for multiple indirection
[...] I am just curious why we have it for
command-line options in this case [...]

Because there is no "string" type in C.
If C had a string type (which I'll call 'tstring'),
main could probably be declared as

int main(int argc, tstring argv[])
So far, so good.
>
where argv is an array of tstring.
No, it would be a pointer to the first element in such an array.
>
But ... strings in C are represented by char *.
No, they are represented by a contiguous sequence of characters terminated
by the first null character. They can be pointed to by char *, in the
sense that a char * can point at their first member.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jul 6 '08 #10
"ke************@googlemail.com" <ke************@googlemail.comwrites:
Forgive the somewhat simple question I am sure this will be, but I am
having some problem understanding what: char **argv looks like. For
instance, i know through trial and error that if I do this:

#include <stdio.h>

int main(int argc, char *argv[])
{
int l;
for( l=0; l<argc; l++ )
{
printf("Pointer: %p\tValue: %s\n", argv++, *argv);
}

return 0;
}

And i invoke the above as:

./foo one two three

Then I will see:
0x10202 foo
0x10204 one
0x10208 two
ox1020c three

Listed, but I would have expected to have needed to write:

*(*(argv))

So as to dereference what the pointer that *argv pointed to. Or have
I missed the point?
argv is of type char**, so *argv is of type char*.

printf() with the "%s" format expects an argument of type char*,
which must point to the first character of a string. printf itself
will dereference this char* pointer to extract and print the
characters of the string.

Incidentally, "%p" is the correct format for printing a pointer
value, but it expects an argument of type void*. If you want to
print a pointer of some other type, you should cast it to void*.

Finally, some style points (oh, here goes Keith with his "style
points" again).

"l" isn't a great name for a variable; it looks too much like the
digit 1 (and can be indistinguishable in some fonts).

Some would argue that modifying a function argument is poor style.
I don't agree, but modifying argv while leaving argc alone is odd.
An idiom I've seen for traversing command-line arguments is to
increment argv while decrementing argc. Or you can just use an
integer to loop through the arguments, leaving argc and argv alone.
(If you're concerned that indexing will be slower than stepping
through with a pointer, don't be; the difference will be minimal,
and a good optimizing compiler will likely generate the same code
either way.)

Of course none of this is a big deal for a program this small, but
small programs are where you should start to develop good habits.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 6 '08 #11
Richard Heathfield wrote:
ba******@gmail.com said:
>ke************@googlemail.com wrote:
>>So again: Why the need for multiple indirection
[...] I am just curious why we have it for
command-line options in this case [...]
Because there is no "string" type in C.
If C had a string type (which I'll call 'tstring'),
main could probably be declared as

int main(int argc, tstring argv[])

So far, so good.
>where argv is an array of tstring.

No, it would be a pointer to the first element in such an array.
>But ... strings in C are represented by char *.

No, they are represented by a contiguous sequence of characters terminated
by the first null character. They can be pointed to by char *, in the
sense that a char * can point at their first member.
No, a string IS a contiguous sequence (an array) of characters
terminated by (and including) the first null character. A string is
referred to by the address (of type char*) of its first member.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jul 6 '08 #12
"ke************@googlemail.com" wrote:
>
.... snip ...
>
I suppose understand conceptually how type_t **foo works -- i do have
to ask *why* the command-line options to a program is in the form:

char **foo

As opposed to a singular array of chars, i,e,:

char foo[SOME_MAX_VALUE]
Because those don't have the same meaning. However you can freely
replace "char **argv" with "char *argv[]" in the parameter list.
Note the added '*'.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Jul 6 '08 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
by: Steven T. Hatton | last post by:
The short sample program listed below has some features that I find to be bad style. In particular, they fail to communicate the connection between names used in this program and the location in...
10
by: JKop | last post by:
Why isn't: int main(int argc, char* argv) { /* ... */ } as: int main(int argc, const char* argv)
21
by: Bret | last post by:
I'm curious why char** argv is acceptable in the main() declaration. In the comp.lang.c FAQ (question 6.18) it says that pointers to pointers and pointers to an array are not interchangable. ...
10
by: David | last post by:
what's the differences between: int main(int argc,char* argv){ ... } and: int main(int argc,char** argv){ ...
14
by: Hal Styli | last post by:
Is this a style thing? int main(int argc, char *argv ) or int main(int argc, char **argv ) i.e. *argv or **argv Why choose the latter?
7
by: =?Utf-8?B?Vmlu?= | last post by:
Hi, I have a question. I created a simple executable program using Visual C++ from Visual Studio 6.0 This program is called from a script that passes in one argument. Now, my question is: ...
8
by: oogie | last post by:
Hi, The arguments to main are usually passed as char* argv or char ** argv, where for this example argv is the array of arguments. What I don't understand is how accessing the actual argument...
24
by: Logan | last post by:
Why (I) works but (II) gives segmentation error? (I) int main(int argc, char *argv) { printf("%s", argv); } (II) int main(int argc, char *argv) { printf("%s", argv);
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.