char* argv[]

Discussion in 'C Programming' started by Logan, Dec 14, 2007.

  1. Logan

    Logan Guest

    Why (I) works but (II) gives segmentation error?

    (I)
    int main(int argc, char *argv[]) {
    printf("%s", argv[0]);
    }

    (II)
    int main(int argc, char *argv) {
    printf("%s", argv[0]);
    }
     
    Logan, Dec 14, 2007
    #1
    1. Advertising

  2. Logan said:

    > Why (I) works but (II) gives segmentation error?
    >
    > (I)
    > int main(int argc, char *argv[]) {
    > printf("%s", argv[0]);
    > }
    >
    > (II)
    > int main(int argc, char *argv) {
    > printf("%s", argv[0]);
    > }


    The behaviour of both programs is undefined, because you don't have a
    prototype in scope for printf, which is a variadic function.

    The first program is otherwise correct (although non-robust, since it
    assumes that argc is at least 1), although adding a return statement with
    an appropriate return value would be wise.

    The second program incorrectly describes the second parameter of main. The
    two correct forms of main are:

    int main(void) /* or any exact semantic equivalent */
    int main(int argc, char **argv) /* or any exact semantic equivalent */

    Your second program thinks argv is a string, which it isn't.

    --
    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
     
    Richard Heathfield, Dec 14, 2007
    #2
    1. Advertising

  3. Logan

    Logan Guest

    Fri, 14 Dec 2007 23:30:39 +0000¿¡, Richard Heathfield ½è½À´Ï´Ù:

    > Logan said:
    >
    >> Why (I) works but (II) gives segmentation error?
    >>
    >> (I)
    >> int main(int argc, char *argv[]) {
    >> printf("%s", argv[0]);
    >> }
    >>
    >> (II)
    >> int main(int argc, char *argv) {
    >> printf("%s", argv[0]);
    >> }

    >
    > The behaviour of both programs is undefined, because you don't have a
    > prototype in scope for printf, which is a variadic function.
    >
    > The first program is otherwise correct (although non-robust, since it
    > assumes that argc is at least 1), although adding a return statement with
    > an appropriate return value would be wise.
    >
    > The second program incorrectly describes the second parameter of main. The
    > two correct forms of main are:
    >
    > int main(void) /* or any exact semantic equivalent */
    > int main(int argc, char **argv) /* or any exact semantic equivalent */
    >
    > Your second program thinks argv is a string, which it isn't.


    Is char **argv equal to char *argv[]?
     
    Logan, Dec 14, 2007
    #3
  4. Logan

    Default User Guest

    Logan wrote:

    > Why (I) works but (II) gives segmentation error?
    >
    > (I)
    > int main(int argc, char *argv[]) {
    > printf("%s", argv[0]);
    > }
    >
    > (II)
    > int main(int argc, char *argv) {
    > printf("%s", argv[0]);
    > }



    Why do you think they are the same? In case II, argv is a pointer to
    char (not a Standard signature for main()). Dereferencing that gives
    you a single character. You then pass it to printf when it expects a
    pointer to char.




    Brian
     
    Default User, Dec 14, 2007
    #4
  5. Logan

    Ben Pfaff Guest

    Richard Heathfield <> writes:

    > Logan said:
    >> (I)
    >> int main(int argc, char *argv[]) {
    >> printf("%s", argv[0]);
    >> }

    >
    > The behaviour of both programs is undefined, because you don't have a
    > prototype in scope for printf, which is a variadic function.
    >
    > The first program is otherwise correct (although non-robust, since it
    > assumes that argc is at least 1), although adding a return statement with
    > an appropriate return value would be wise.


    It also fails to write a new-line to stdout to complete the
    output line, although I suppose argv[0] could theoretically end
    in a new-line.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
     
    Ben Pfaff, Dec 14, 2007
    #5
  6. Logan said:

    <snip>

    > Is char **argv equal to char *argv[]?


    In this context (formal parameters in a function declaration), yes, they
    are equivalent.

    --
    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
     
    Richard Heathfield, Dec 14, 2007
    #6
  7. Logan

    Ben Pfaff Guest

    Logan <> writes:

    > Is char **argv equal to char *argv[]?


    In a function prototype, they are semantically equivalent. The
    latter suggests to human readers that the argument is an array,
    but the compiler will treat the two declarations identically.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
     
    Ben Pfaff, Dec 14, 2007
    #7
  8. Logan

    Guest


    >The first program is otherwise correct (although non-robust, since it
    >assumes that argc is at least 1)


    argc will always be atleast one.

    On Dec 15, 4:30 am, Richard Heathfield <> wrote:
    > Logan said:
    >
    > > Why (I) works but (II) gives segmentation error?

    >
    > > (I)
    > > int main(int argc, char *argv[]) {
    > > printf("%s", argv[0]);
    > > }

    >
    > > (II)
    > > int main(int argc, char *argv) {
    > > printf("%s", argv[0]);
    > > }

    >
    > The behaviour of both programs is undefined, because you don't have a
    > prototype in scope for printf, which is a variadic function.
    >
    > The first program is otherwise correct (although non-robust, since it
    > assumes that argc is at least 1), although adding a return statement with
    > an appropriate return value would be wise.
    >
    > The second program incorrectly describes the second parameter of main. The
    > two correct forms of main are:
    >
    > int main(void) /* or any exact semantic equivalent */
    > int main(int argc, char **argv) /* or any exact semantic equivalent */
    >
    > Your second program thinks argv is a string, which it isn't.
    >
    > --
    > 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



    >The first program is otherwise correct (although non-robust, since it

    assumes that argc is at least 1)

    argc will always be atleast one.
     
    , Dec 15, 2007
    #8
  9. Logan

    pete Guest

    wrote:

    > argc will always be atleast one.


    That's not what the C standard says.

    N869
    5.1.2.2 Hosted environment
    5.1.2.2.1 Program startup

    [#2] If they are declared, the parameters to the main
    function shall obey the following constraints:

    -- If the value of argc is greater than zero, the string
    pointed to by argv[0] represents the program name;
    argv[0][0] shall be the null character if the program
    name is not available from the host environment. If
    the value of argc is greater than one, the strings
    pointed to by argv[1] through argv[argc-1] represent
    the program parameters.


    --
    pete
     
    pete, Dec 15, 2007
    #9
  10. said:

    > Richard Heathfield wrote:
    >
    >>The first program is otherwise correct (although non-robust, since it
    >>assumes that argc is at least 1)

    >
    > argc will always be atleast one.


    This is not guaranteed by the Standard. See 2.1.2.2 of C89 or 5.1.2.2.1 of
    C99.

    It is generally a good idea to check your facts before issuing a
    "correction".

    --
    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
     
    Richard Heathfield, Dec 15, 2007
    #10
  11. Logan

    Joe Wright Guest

    Richard Heathfield wrote:
    > said:
    >
    >> Richard Heathfield wrote:
    >>
    >>> The first program is otherwise correct (although non-robust, since it
    >>> assumes that argc is at least 1)

    >> argc will always be atleast one.

    >
    > This is not guaranteed by the Standard. See 2.1.2.2 of C89 or 5.1.2.2.1 of
    > C99.
    >
    > It is generally a good idea to check your facts before issuing a
    > "correction".
    >

    What is the case (are the cases) for argc == 0?

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Dec 15, 2007
    #11
  12. In article <>,
    Joe Wright <> wrote:
    >What is the case (are the cases) for argc == 0?


    An operating system that doesn't provide, or allows you not to provide,
    any argv values.

    The version of unix I'm using says that the exec*() functions require
    at least one argument, but POSIX merely says that the first argument
    should be the filename.

    -- Richard
    --
    :wq
     
    Richard Tobin, Dec 15, 2007
    #12
  13. On Sat, 15 Dec 2007 10:20:24 +1100, Logan
    <> wrote:

    >Why (I) works but (II) gives segmentation error?
    >
    >(I)
    >int main(int argc, char *argv[]) {
    > printf("%s", argv[0]);
    >}


    argv is an array of pointers. argv[0] is the first pointer in the
    array.

    >
    >(II)
    >int main(int argc, char *argv) {
    > printf("%s", argv[0]);
    >}


    argv is a pointer to char. argv[0] is the char itself.

    What type of parameter must you use to match a %s?


    Remove del for email
     
    Barry Schwarz, Dec 19, 2007
    #13
  14. On Sat, 15 Dec 2007 10:30:55 +1100, Logan
    <> wrote:

    >Fri, 14 Dec 2007 23:30:39 +0000¿¡, Richard Heathfield ½è½À´Ï´Ù:
    >
    >> Logan said:
    >>
    >>> Why (I) works but (II) gives segmentation error?
    >>>
    >>> (I)
    >>> int main(int argc, char *argv[]) {
    >>> printf("%s", argv[0]);
    >>> }
    >>>
    >>> (II)
    >>> int main(int argc, char *argv) {
    >>> printf("%s", argv[0]);
    >>> }

    >>
    >> The behaviour of both programs is undefined, because you don't have a
    >> prototype in scope for printf, which is a variadic function.
    >>
    >> The first program is otherwise correct (although non-robust, since it
    >> assumes that argc is at least 1), although adding a return statement with
    >> an appropriate return value would be wise.
    >>
    >> The second program incorrectly describes the second parameter of main. The
    >> two correct forms of main are:
    >>
    >> int main(void) /* or any exact semantic equivalent */
    >> int main(int argc, char **argv) /* or any exact semantic equivalent */
    >>
    >> Your second program thinks argv is a string, which it isn't.

    >
    >Is char **argv equal to char *argv[]?


    Only in certain contexts. With three exceptions, an expression (not a
    declaration) with array type is converted to the address of the first
    element with type pointer to element type.

    So immediately you know that
    char *argv1[10];
    char **argv2;
    produce very different type of objects.

    However, given the above
    argv2 = argv1;
    is legal and is exactly equivalent to
    argv2 = &argv1[0];

    In the case of a function declaration, the actual arguments are
    "passed" to the formal parameters as if by assignment. Consequently,
    even if your parameter list specifies an array, the compiler knows
    better and generates code to process the pointer that is actually
    passed.

    This is the reason that
    char *x1 = "Hello,";
    char x2[] = " world";
    printf("%s%s\n", x1, x2)
    works even though x1 is a pointer and x2 is an array.


    Remove del for email
     
    Barry Schwarz, Dec 19, 2007
    #14
  15. Barry Schwarz said:
    > Logan wrote:


    <snip>

    >>int main(int argc, char *argv[]) {
    >>printf("%s", argv[0]);
    >>}

    >
    > argv is an array of pointers.


    No, it's a pointer to the first element in an array of pointers.

    --
    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
     
    Richard Heathfield, Dec 19, 2007
    #15
  16. Barry Schwarz <> writes:
    > On Sat, 15 Dec 2007 10:30:55 +1100, Logan
    > <> wrote:

    [...]
    >>Is char **argv equal to char *argv[]?

    >
    > Only in certain contexts. With three exceptions, an expression (not a
    > declaration) with array type is converted to the address of the first
    > element with type pointer to element type.
    >
    > So immediately you know that
    > char *argv1[10];
    > char **argv2;
    > produce very different type of objects.
    >
    > However, given the above
    > argv2 = argv1;
    > is legal and is exactly equivalent to
    > argv2 = &argv1[0];
    >
    > In the case of a function declaration, the actual arguments are
    > "passed" to the formal parameters as if by assignment. Consequently,
    > even if your parameter list specifies an array, the compiler knows
    > better and generates code to process the pointer that is actually
    > passed.
    >
    > This is the reason that
    > char *x1 = "Hello,";
    > char x2[] = " world";
    > printf("%s%s\n", x1, x2)
    > works even though x1 is a pointer and x2 is an array.


    There are actually two independent language rules in play here.

    The one you describe (that an expression of array type is
    automatically converted to a pointer in most contexts) says nothing
    about declarations such as ``char **argv'' or ``char *argv[]''.

    There's a separate special rule for parameter declarations that says
    that something that looks like an array parameter declaration is
    really a pointer declaration. Note that this rule doesn't involve any
    (run-time) type conversions; it describes two constructs as being
    exactly equivalent.

    These two rules work together to allow lazy programmers to pretend
    that arrays and pointers are the same thing.

    The array-to-pointer conversion rule is almost impossible to avoid.
    The parameter declaration rule can be avoided (and IMHO should be)
    simply by declaring parameters as pointers.

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 19, 2007
    #16
  17. On Dec 14, 11:30 pm, Richard Heathfield <> wrote:
    > Logan said:


    > > int main(int argc, char *argv) {

    <snip>
    >
    > Your second program thinks argv is a string, which it isn't.


    No. In the second program, argv is a pointer to
    an array of characters. C doesn't have a string type.
     
    William Pursell, Dec 19, 2007
    #17
  18. William Pursell said:

    > On Dec 14, 11:30 pm, Richard Heathfield <> wrote:
    >> Logan said:

    >
    >> > int main(int argc, char *argv) {

    > <snip>
    >>
    >> Your second program thinks argv is a string, which it isn't.

    >
    > No.


    Your "correction" is incorrect.

    > In the second program, argv is a pointer to
    > an array of characters.


    No, in the second program argv is (incorrectly defined as) a pointer to the
    *first element* in an array of characters. The program then uses this
    value as an argument matching a printf %s format specifier - in other
    words, the program thinks argv is a string (just as I claimed), and is
    using it as one.

    > C doesn't have a string type.


    Non sequitur. I didn't claim that C has a string type.

    --
    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
     
    Richard Heathfield, Dec 19, 2007
    #18
  19. Richard Heathfield <> writes:
    > William Pursell said:
    >> On Dec 14, 11:30 pm, Richard Heathfield <> wrote:
    >>> Logan said:
    >>> > int main(int argc, char *argv) {

    >> <snip>
    >>>
    >>> Your second program thinks argv is a string, which it isn't.

    >>
    >> No.

    >
    > Your "correction" is incorrect.
    >
    >> In the second program, argv is a pointer to
    >> an array of characters.

    >
    > No, in the second program argv is (incorrectly defined as) a pointer to the
    > *first element* in an array of characters. The program then uses this
    > value as an argument matching a printf %s format specifier


    Right.

    > - in other
    > words, the program thinks argv is a string (just as I claimed), and is
    > using it as one.


    Nope. argv is a pointer. A string is "a contiguous sequence of
    characters terminated by and including the first null character".
    A pointer cannot be a string. [*]

    Quoting the program in the orginal post:

    | (I)
    | int main(int argc, char *argv[]) {
    | printf("%s", argv[0]);
    | }
    |
    | (II)
    | int main(int argc, char *argv) {
    | printf("%s", argv[0]);
    | }

    Neither program assumes that argv is either a string or a pointer to a
    string. Both programs assume (in their respective printf calls) that
    ``argv[0]'' is *a pointer to* a string (defined by the standard as "a
    pointer to its initial (lowest addressed) character" of a string). In
    the first program, this assumption is correct if argc is greater than
    zero. In the second program, this assumption is incorrect; argv[0] is
    a single char (assuming the implementation allows the rather odd
    declaration of main).

    >> C doesn't have a string type.

    >
    > Non sequitur. I didn't claim that C has a string type.


    But it does define precisely what a string is.

    [*] Well, I suppose a pointer could be a string if its representation,
    as a sequence of bytes, happens to include a null byte, but that's not
    what was meant.

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 19, 2007
    #19
  20. Keith Thompson said:

    <snip>

    > A pointer cannot be a string. [*]


    I have been out-nitted. Yes, of course I mean that the program is treating
    argv as a pointer to the first character in a string.

    <snip>

    --
    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
     
    Richard Heathfield, Dec 19, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bret

    char **argv vs. char* argv[]

    Bret, Aug 31, 2003, in forum: C Programming
    Replies:
    21
    Views:
    4,704
    Richard Heathfield
    Sep 3, 2003
  2. David
    Replies:
    10
    Views:
    6,075
    Richard Heathfield
    Sep 15, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,715
    Old Wolf
    Jan 20, 2004
  4. jab3

    char **argv & char *argv[]

    jab3, Dec 4, 2004, in forum: C Programming
    Replies:
    5
    Views:
    721
    Chris Torek
    Dec 8, 2004
  5. oogie
    Replies:
    9
    Views:
    685
    Default User
    Nov 18, 2007
Loading...

Share This Page