char **argv vs. char* argv[]

Discussion in 'C Programming' started by Bret, Aug 31, 2003.

  1. Bret

    Bret Guest

    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. However the
    declaration:

    int main(int argc, char** argv)

    is common.

    How does that work out? Shouldn't the compiler complain if you're not
    doing:

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

    Thanks,
    Bret
     
    Bret, Aug 31, 2003
    #1
    1. Advertising

  2. Bret <> scribbled the following:
    > 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. However the
    > declaration:


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


    > is common.


    > How does that work out? Shouldn't the compiler complain if you're not
    > doing:


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


    This is because in function parameter declarations, char **foo and
    char *foo[] are the same thing. Not just in main(), but in every other
    function too. What's more, int **foo and int *foo[] are also the same.
    So are int ***foo and int **foo[].
    In fact, in general, if T is a type, then T *foo and T foo[] are the
    same thing in function parameter declarations. (This goes ONLY one
    level deep - T **foo and T foo[][] are a different matter entirely!)
    This is all explained by Chris Torek's THE RULE. If used as a value,
    or as a function parameter, an array decays into a pointer into its
    first element. Therefore you can't really pass arrays into functions
    at all. You can pass pointers to arrays, or structures containing
    arrays, but not arrays themselves.

    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "Roses are red, violets are blue, I'm a schitzophrenic and so am I."
    - Bob Wiley
     
    Joona I Palaste, Aug 31, 2003
    #2
    1. Advertising

  3. In article <>,
    Bret <> wrote:
    >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. However the
    >declaration:
    >
    >int main(int argc, char** argv)
    >
    >is common.


    char **argv declares argv as a pointer to a pointer to a character
    char *argv[] declares argv as am array of pointers to a character

    There are no pointers to arrays in either case. So whether or not
    pointers to arrays are interchangable with pointers to pointers is
    irrelevant to whether "char **argv" and "char *argv[]" are both
    allowable as the second parameter to main().

    The relevant question you would want to ask is whether arrays and
    pointers are interchangable. They aren't in the general case, in the
    formal parameter list of a function, they more-or-less are with respect
    to the outer-most nesting layer.

    -- Brett
     
    Brett Frankenberger, Aug 31, 2003
    #3
  4. Bret wrote:

    > 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 interchangeable.
    > However the declaration:
    >
    > int main(int argc, char** argv)
    >
    > is common.
    >
    > How does that work out?
    > Shouldn't the compiler complain if you're not doing:
    >
    > int main(int argc, char* argv[])


    It probably should complain.

    > cat f.c

    int f(char* s[]) {
    char** p = s;
    }

    > gcc -Wall -std=c99 -pedantic -c f.c

    f.c: In function `f':
    f.c:2: warning: unused variable `p'
    f.c:3: warning: control reaches end of non-void function

    C performs an "implicit conversion"
    from an array to a pointer to its first element
    and from a pointer to an array.

    I can write

    > cat f.c

    int f(char* s[]) {
    char** p = s;
    return f(p);
    }

    > gcc -Wall -std=c99 -pedantic -c f.c


    and my compiler will not complain.
     
    E. Robert Tisdale, Aug 31, 2003
    #4
  5. "E. Robert Tisdale" <> wrote in
    <>:

    >> Shouldn't the compiler complain if you're not doing:
    >>
    >> int main(int argc, char* argv[])

    >
    >It probably should complain.


    Why?

    > > cat f.c

    > int f(char* s[]) {
    > char** p = s;
    > }
    >
    > > gcc -Wall -std=c99 -pedantic -c f.c

    > f.c: In function `f':
    > f.c:2: warning: unused variable `p'
    > f.c:3: warning: control reaches end of non-void function


    Your compiler complains about you having declared an automatic variable
    without using it and to not return a value from a function that is
    declared as returning int. This has no relation to the given problem.

    >C performs an "implicit conversion"
    >from an array to a pointer to its first element


    Right, when used as a value or formal parameter.

    >and from a pointer to an array.


    Huh?
    ITYM one can apply the '[]' operator to a pointer like
    one would do with an array, so that:

    int i = 21;
    int a[42];
    int *p = a;

    leads to:

    p == a;

    >
    >I can write
    >
    > > cat f.c

    > int f(char* s[]) {
    > char** p = s;
    > return f(p);
    > }
    >
    > > gcc -Wall -std=c99 -pedantic -c f.c

    >
    >and my compiler will not complain.


    Yes, because this time you use p *and* you (formally) return a
    value while in fact f() won't return anything at all as it will
    crash your program when called because of infinite recursion.

    Irrwahn

    --
    If it's not on fire, it's a software problem.
     
    Irrwahn Grausewitz, Aug 31, 2003
    #5
  6. Irrwahn Grausewitz wrote:

    > E. Robert Tisdale wrote:
    >
    >>>Shouldn't the compiler complain if you're not doing:
    >>>
    >>> int main(int argc, char* argv[])

    >>
    >>It probably should complain.

    >
    > Why?
    >
    >> > cat f.c

    >> int f(char* s[]) {
    >> char** p = s;
    >> }
    >>
    >> > gcc -Wall -std=c99 -pedantic -c f.c

    >> f.c: In function `f':
    >> f.c:2: warning: unused variable `p'
    >> f.c:3: warning: control reaches end of non-void function

    >
    > Your compiler complains about you having declared an automatic variable
    > without using it and to not return a value from a function that is
    > declared as returning int. This has no relation to the given problem.
    >
    >>C performs an "implicit conversion"

    >
    >>from an array to a pointer to its first element

    >
    > Right, when used as a value or formal parameter.
    >
    >>and from a pointer to an array.

    >
    > Huh?
    > ITYM one can apply the '[]' operator to a pointer like
    > one would do with an array, so that:
    >
    > int i = 21;
    > int a[42];
    > int *p = a;
    >
    > leads to:
    >
    > p == a;
    >
    >>I can write
    >>
    >> > cat f.c

    >> int f(char* s[]) {
    >> char** p = s;
    >> return f(p);
    >> }
    >>
    >> > gcc -Wall -std=c99 -pedantic -c f.c

    >>
    >>and my compiler will not complain.

    >
    > Yes, because this time you use p *and* you (formally) return a
    > value while in fact f() won't return anything at all as it will
    > crash your program when called because of infinite recursion.


    Now that you've caught up with everyone else, please explain

    > expand f.c

    #include <stdio.h>

    int f(char* s[10]) {
    char** p = s;
    fprintf(stdout, "%d = sizeof(s)\n", sizeof(s));
    fprintf(stdout, "%d = sizeof(p)\n", sizeof(p));
    return 0;
    }

    int main(int argc, char* argv[]) {
    char * s[10];
    fprintf(stdout, "%d = sizeof(s)\n", sizeof(s));
    return f(s);
    }

    > gcc -Wall -std=c99 -pedantic -o main f.c
    > ./main

    40 = sizeof(s)
    4 = sizeof(s)
    4 = sizeof(p)
     
    E. Robert Tisdale, Aug 31, 2003
    #6
  7. On Mon, 1 Sep 2003, Irrwahn Grausewitz wrote:
    >
    > "E. Robert Tisdale" <> wrote in
    > <>:
    >
    > >Now that you've caught up with everyone else, please explain
    > >
    > > > gcc -Wall -std=c99 -pedantic -o main f.c
    > > > ./main

    > > 40 = sizeof(s)
    > > 4 = sizeof(s)
    > > 4 = sizeof(p)

    >
    > All I can see is that on your system
    > 10*sizeof(char*) == 40 and sizeof(char**) == 4.
    > Not very surprisingly, I have to add.
    >
    > Where's the joke?



    Tisdale is a troll. Please just correct his posts quietly and
    move away; or just ignore them, as I've learned to do. (And
    yes, the "is he really at NASA?" question has been beaten to
    death several times already. Check Google Groups.)

    -Arthur
     
    Arthur J. O'Dwyer, Aug 31, 2003
    #7
  8. E. Robert Tisdale wrote:

    > Now that you've caught up with everyone else,


    Don't be unpleasant, especially when you're wrong.

    > please explain


    Delighted.

    > > expand f.c


    Syntax error.

    > #include <stdio.h>
    >
    > int f(char* s[10]) {
    > char** p = s;
    > fprintf(stdout, "%d = sizeof(s)\n", sizeof(s));
    > fprintf(stdout, "%d = sizeof(p)\n", sizeof(p));


    At the very least, on systems where a size_t is larger than an int the
    behaviour is undefined.

    Note that your demo program doesn't meet the requirements of the question,
    which nowhere mentions char *s[10]. Still, never mind that. Observe:

    rjh@tux:~/scratch> cat foo.c
    #include <stdio.h>

    void foo(char **r, char *s[], char *t[10])
    {
    printf("sizeof r = %lu\n", (unsigned long)sizeof r);
    printf("sizeof s = %lu\n", (unsigned long)sizeof s);
    printf("sizeof t = %lu\n", (unsigned long)sizeof t);
    }

    int main(int argc, char **argv)
    {
    if(argc >= 10)
    {
    foo(argv, argv, argv);
    }
    else
    {
    char *tmp[10];
    foo(argv, argv, tmp);
    }
    return 0;
    }

    rjh@tux:~/scratch> ./foo 1 2 3 4 5 6 7 8 9 10
    sizeof r = 4
    sizeof s = 4
    sizeof t = 4


    Now for some history. Here are the first few lines of the source code from a
    ***very*** early C compiler. Regular readers will note the irony of my
    quoting from it:

    /* C compiler

    Copyright 1972 Bell Telephone Laboratories, Inc.

    */

    ossiz 250;
    ospace() {} /* fake */

    init(s, t)
    char s[]; {
    extern lookup, symbuf, namsiz;
    char symbuf[], sp[];
    int np[], i;

    i = namsiz;
    sp = symbuf;
    while(i--)
    if ((*sp++ = *s++)=='\0') --s;
    np = lookup();
    *np++ = 1;
    *np = t;
    }

    Note the usage of np, which is defined as int np[], and used like this:
    *np++ = 1;

    Clearly, this is pointer syntax. [] was, in fact, used for pointer notation
    early in C's development. Eventually, it was changed, but the usage of []
    in function parameter lists lives on. It /still/ means pointer, in that
    context.

    Brian W Kernighan writes, in K&R2 starting at the foot of p99, "As formal
    parameters in a function definition, char s[]; and char *s; are equivalent;
    we prefer the latter because it says more explicitly that the parameter is
    a pointer."

    I don't expect Mr Tisdale to understand this, of course, but some other
    people might find it interesting.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Sep 1, 2003
    #8
  9. Richard Heathfield wrote:

    >
    > Note that your demo program doesn't meet the requirements of the question,
    > which nowhere mentions char *s[10]. Still, never mind that. Observe:
    >
    > > cat foo.c
    > #include <stdio.h>
    >
    > void foo(char **r, char *s[], char *t[10]) {
    > printf("sizeof r = %lu\n", (unsigned long)sizeof r);
    > printf("sizeof s = %lu\n", (unsigned long)sizeof s);
    > printf("sizeof t = %lu\n", (unsigned long)sizeof t);
    > }
    >
    > int main(int argc, char* argv[]) {
    > if(argc >= 10) {
    > foo(argv, argv, argv);
    > }
    > else {
    > char *tmp[10];
    > foo(argv, argv, tmp);
    > }
    > return 0;
    > }
    >
    > > ./foo 1 2 3 4 5 6 7 8 9 10
    > sizeof r = 4
    > sizeof s = 4
    > sizeof t = 4
    >
    > Now for some history.
    > Here are the first few lines of the source code
    > from a ***very*** early C compiler.
    > Regular readers will note the irony of my quoting from it:
    >
    > /* C compiler
    >
    > Copyright 1972 Bell Telephone Laboratories, Inc.
    >
    > */
    >
    > ossiz 250;
    > ospace() {} /* fake */
    >
    > init(s, t)
    > char s[]; {
    > extern lookup, symbuf, namsiz;
    > char symbuf[], sp[];
    > int np[], i;
    >
    > i = namsiz;
    > sp = symbuf;
    > while(i--)
    > if ((*sp++ = *s++)=='\0') --s;
    > np = lookup();
    > *np++ = 1;
    > *np = t;
    > }
    >
    > Note the usage of np, which is defined as int np[], and used like this:
    > *np++ = 1;
    >
    > Clearly, this is pointer syntax. [] was, in fact, used for pointer notation
    > early in C's development. Eventually, it was changed
    > but the usage of [] in function parameter lists lives on.
    > It /still/ means pointer, in that context.
    >
    > Brian W Kernighan writes, in K&R2 starting at the foot of p99,
    > "As formal parameters in a function definition,
    > char s[]; and char *s; are equivalent; we prefer the latter
    > because it says more explicitly that the parameter is a pointer."


    That's pretty good.
    Now, perhaps you are ready to answer Bret's question,
    "Shouldn't the compiler complain if you're not doing:

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

    The answer is that it should. I don't know why it doesn't.
    It appears that you believe that
    the reason has something to do with legacy code
    which treats T t[] as pointer syntax like T t*
    *in a function argument list*.
    Please cite and quote the relevant *rational*
    from the ANSI/ISO C standard if you can.


    > I don't expect Mr Tisdale to understand this, of course,
    > but some other people might find it interesting.


    Don't be unpleasant, especially when you're wrong.
     
    E. Robert Tisdale, Sep 1, 2003
    #9
  10. Arthur J. O'Dwyer wrote:

    > Tisdale is a troll. Please just correct his posts quietly
    > and move away; or just ignore them, as I've learned to do.
    > (... Check Google Groups.)


    I checked Google Groups and searched for

    Dwyer troll

    in the comp.lang.c newsgroup.
    It seems that, whenever you lose and argument,
    you accuse your opponent of being a troll. ;-)
     
    E. Robert Tisdale, Sep 1, 2003
    #10
  11. "E. Robert Tisdale" <> wrote:
    >Please cite and quote the relevant *rational*
    >from the ANSI/ISO C standard if you can.

    Read JTC1/SC22/WG14 N843 6.7.5.3#6 if you can,
    then rip out the page, eat it & choke.

    --
    Yah, I know, I should not feed the trolls.
     
    Irrwahn Grausewitz, Sep 1, 2003
    #11
  12. E. Robert Tisdale wrote:

    <snip>

    > Now, perhaps you are ready to answer Bret's question,
    > "Shouldn't the compiler complain if you're not doing:
    >
    > int main(int argc, char* argv[])?"


    The compiler may issue a diagnostic for any reason it likes, but it is not
    required to issue a diagnostic for int main(int argc, char **argv).

    >
    > The answer is that it should.


    It is not required so to do. See the Standard. The usual section.

    > I don't know why it doesn't.


    I do.

    > It appears that you believe that
    > the reason has something to do with legacy code
    > which treats T t[] as pointer syntax like T t*
    > *in a function argument list*.


    That is not (precisely) the reason that no diagnostic is required. The
    reason no diagnostic is required is that no syntax error or constraint
    violation is involved.

    > Please cite and quote the relevant *rational*
    > from the ANSI/ISO C standard if you can.


    See 5.1.2.2.1 of ISO/IEC 9899:1999.

    >> I don't expect Mr Tisdale to understand this, of course,
    >> but some other people might find it interesting.

    >
    > Don't be unpleasant, especially when you're wrong.


    Nice try, but I'm not wrong, and I wasn't being unpleasant. I was simply
    pointing out, in that first clause, that I don't think you are capable of
    understanding what I had written. It appears, from your reply, that I was
    pretty close to the mark.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Sep 1, 2003
    #12
  13. Bret

    j Guest

    "E. Robert Tisdale" <> wrote in message news:<>...
    > Richard Heathfield wrote:
    >
    > >
    > > Note that your demo program doesn't meet the requirements of the question,
    > > which nowhere mentions char *s[10]. Still, never mind that. Observe:
    > >
    > > > cat foo.c
    > > #include <stdio.h>
    > >
    > > void foo(char **r, char *s[], char *t[10]) {
    > > printf("sizeof r = %lu\n", (unsigned long)sizeof r);
    > > printf("sizeof s = %lu\n", (unsigned long)sizeof s);
    > > printf("sizeof t = %lu\n", (unsigned long)sizeof t);
    > > }
    > >
    > > int main(int argc, char* argv[]) {
    > > if(argc >= 10) {
    > > foo(argv, argv, argv);
    > > }
    > > else {
    > > char *tmp[10];
    > > foo(argv, argv, tmp);
    > > }
    > > return 0;
    > > }

    >
    > > > ./foo 1 2 3 4 5 6 7 8 9 10
    > > sizeof r = 4
    > > sizeof s = 4
    > > sizeof t = 4
    > >
    > > Now for some history.
    > > Here are the first few lines of the source code
    > > from a ***very*** early C compiler.
    > > Regular readers will note the irony of my quoting from it:
    > >
    > > /* C compiler
    > >
    > > Copyright 1972 Bell Telephone Laboratories, Inc.
    > >
    > > */
    > >
    > > ossiz 250;
    > > ospace() {} /* fake */
    > >
    > > init(s, t)
    > > char s[]; {
    > > extern lookup, symbuf, namsiz;
    > > char symbuf[], sp[];
    > > int np[], i;
    > >
    > > i = namsiz;
    > > sp = symbuf;
    > > while(i--)
    > > if ((*sp++ = *s++)=='\0') --s;
    > > np = lookup();
    > > *np++ = 1;
    > > *np = t;
    > > }
    > >
    > > Note the usage of np, which is defined as int np[], and used like this:
    > > *np++ = 1;
    > >
    > > Clearly, this is pointer syntax. [] was, in fact, used for pointer notation
    > > early in C's development. Eventually, it was changed
    > > but the usage of [] in function parameter lists lives on.
    > > It /still/ means pointer, in that context.
    > >
    > > Brian W Kernighan writes, in K&R2 starting at the foot of p99,
    > > "As formal parameters in a function definition,
    > > char s[]; and char *s; are equivalent; we prefer the latter
    > > because it says more explicitly that the parameter is a pointer."

    >
    > That's pretty good.
    > Now, perhaps you are ready to answer Bret's question,
    > "Shouldn't the compiler complain if you're not doing:
    >
    > int main(int argc, char* argv[])?"


    You can either use ``char *argv[]'' or ``char **argv'' or if not
    passing any arguments to main, then ``int main(void)''. In all cases
    the compiler won't complain. Although this brings me to wondering
    about something. In section 6.11.6 of c99 it says:

    "6.11.6 Function declarators
    1 The use of function declarators with empty parentheses (not
    prototype-format parameter
    type declarators) is an obsolescent feature."

    So something like:

    int foo(); would be considered obsolescent?


    Also, would:

    int main() /* This falls in 6.11.6? */
    {
    return 0;
    }

    The second example of main, it being part of a function definition, is
    what is throwing me off and am unsure if it is considered obsolescent
    as stated in 6.11.6.


    >
    > The answer is that it should. I don't know why it doesn't.
    > It appears that you believe that
    > the reason has something to do with legacy code
    > which treats T t[] as pointer syntax like T t*
    > *in a function argument list*.
    > Please cite and quote the relevant *rational*
    > from the ANSI/ISO C standard if you can.
    >
    >
    > > I don't expect Mr Tisdale to understand this, of course,
    > > but some other people might find it interesting.

    >
    > Don't be unpleasant, especially when you're wrong.
     
    j, Sep 1, 2003
    #13
  14. j wrote:

    > You can either use ``char *argv[]'' or ``char **argv''
    >
    > or if not passing any arguments to main, then ``int main(void)''.
    > In all cases the compiler won't complain.
    > Although this brings me to wondering about something.
    > In section 6.11.6 of c99 it says:
    >
    > "6.11.6 Function declarators
    > 1 The use of function declarators with empty parentheses
    > (not prototype-format parameter type declarators)
    > is an obsolescent feature."
    >
    > So something like:
    >
    > int foo();
    >
    > would be considered obsolescent?
    > Also, would:
    >
    > int main(void) { /* This falls in 6.11.6? */
    > return 0;
    > }
    >
    > The second example of main,
    > it being part of a function definition, is what is throwing me off
    > and am unsure if it is considered obsolescent as stated in 6.11.6.


    I don't know.
    Function main is a special case.
    The application isn't allowed to call it.
    Your definition above would simply ignore any arguments passed to it.

    No doubt, several of our indigenous "spiritualists"
    will cite and quote the ANSI/ISO C "scripture"
    as the reason why but I don't think any of them know
    the *rationale* behind the dictates of the ANSI/ISO C standard.
    Part of the problem is that the reasoning behind decision
    taken collectively are seldom documented in great any detail
    and are lost as time passes. The result is that
    some of what appears in the standard is ritualistic
    based upon superstitious belief.
     
    E. Robert Tisdale, Sep 1, 2003
    #14
  15. Bret

    Kevin Easton Guest

    E. Robert Tisdale <> wrote:
    > j wrote:
    >
    >> You can either use ``char *argv[]'' or ``char **argv''
    >>
    >> or if not passing any arguments to main, then ``int main(void)''.
    >> In all cases the compiler won't complain.


    The compiler doesn't have to complain about *any* incorrect declaration
    of main - but the three you listed are all correct.

    >> Although this brings me to wondering about something.
    >> In section 6.11.6 of c99 it says:
    >>
    >> "6.11.6 Function declarators
    >> 1 The use of function declarators with empty parentheses
    >> (not prototype-format parameter type declarators)
    >> is an obsolescent feature."
    >>
    >> So something like:
    >>
    >> int foo();
    >>
    >> would be considered obsolescent?


    Yes.

    >> Also, would:
    >>
    >> int main(void) { /* This falls in 6.11.6? */
    >> return 0;
    >> }
    >>
    >> The second example of main,
    >> it being part of a function definition, is what is throwing me off
    >> and am unsure if it is considered obsolescent as stated in 6.11.6.


    No, that's not obsolescent, because it's using a prototype-format
    parameter list. On the other hand, this is obsolescent:

    int main()
    {
    return 0;
    }

    (It doesn't matter whether it's a definition or a declaration).

    > I don't know.
    > Function main is a special case.
    > The application isn't allowed to call it.


    No, there's nothing wrong with the program calling its own main()
    function.

    > Your definition above would simply ignore any arguments passed to it.
    >
    > No doubt, several of our indigenous "spiritualists"
    > will cite and quote the ANSI/ISO C "scripture"
    > as the reason why but I don't think any of them know
    > the *rationale* behind the dictates of the ANSI/ISO C standard.
    > Part of the problem is that the reasoning behind decision
    > taken collectively are seldom documented in great any detail
    > and are lost as time passes. The result is that
    > some of what appears in the standard is ritualistic
    > based upon superstitious belief.


    The reason behind obsoleting non-prototyped function declarations and
    definitions is quite clear - because it removes the compiler's ability
    to type-check function calls, and it gains nothing.

    - Kevin.
     
    Kevin Easton, Sep 2, 2003
    #15
  16. E. Robert Tisdale wrote:

    > j wrote:
    >
    >> In section 6.11.6 of c99 it says:
    >>
    >> "6.11.6 Function declarators
    >> 1 The use of function declarators with empty parentheses
    >> (not prototype-format parameter type declarators)
    >> is an obsolescent feature."
    >>
    >> So something like:
    >>
    >> int foo();
    >>
    >> would be considered obsolescent?



    Right.


    >> Also, would:
    >>
    >> int main(void) { /* This falls in 6.11.6? */



    No, it doesn't. The keyword "void" fills the gap. In other words, this is a
    function prototype - a declaration that explicitly documents the types of
    its parameters, with void being used in this case to document that there
    are /no/ parameters.


    >> return 0;
    >> }
    >>
    >> The second example of main,
    >> it being part of a function definition, is what is throwing me off
    >> and am unsure if it is considered obsolescent as stated in 6.11.6.

    >
    > I don't know.


    I do. int main(void) is not obsolescent.

    > Function main is a special case.


    Only in that it is the entry point to the program and must therefore have a
    carefully-defined interface.

    > The application isn't allowed to call it.


    What are you wittering on about now? Of course the application is allowed to
    call it.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Sep 2, 2003
    #16
  17. Bret

    j Guest

    "Richard Heathfield" <> wrote in message
    news:bj17fm$24j$...
    > E. Robert Tisdale wrote:
    >
    > > j wrote:
    > >
    > >> In section 6.11.6 of c99 it says:
    > >>
    > >> "6.11.6 Function declarators
    > >> 1 The use of function declarators with empty parentheses
    > >> (not prototype-format parameter type declarators)
    > >> is an obsolescent feature."
    > >>
    > >> So something like:
    > >>
    > >> int foo();
    > >>
    > >> would be considered obsolescent?

    >
    >
    > Right.
    >
    >
    > >> Also, would:
    > >>
    > >> int main(void) { /* This falls in 6.11.6? */

    >
    >
    > No, it doesn't. The keyword "void" fills the gap. In other words, this is

    a
    > function prototype - a declaration that explicitly documents the types of
    > its parameters, with void being used in this case to document that there
    > are /no/ parameters.
    >


    Hm, in my original question I didn't have a ``void''.. not sure how that
    ended up there.

    >
    > >> return 0;
    > >> }
    > >>
    > >> The second example of main,
    > >> it being part of a function definition, is what is throwing me off
    > >> and am unsure if it is considered obsolescent as stated in 6.11.6.

    > >
    > > I don't know.

    >
    > I do. int main(void) is not obsolescent.
    >
    > > Function main is a special case.

    >
    > Only in that it is the entry point to the program and must therefore have

    a
    > carefully-defined interface.
    >
    > > The application isn't allowed to call it.

    >
    > What are you wittering on about now? Of course the application is allowed

    to
    > call it.
    >
    > --
    > Richard Heathfield :
    > "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    > C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    > K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    j, Sep 2, 2003
    #17
  18. "j" <> wrote in
    <qGW4b.4169$>:
    >"Richard Heathfield" <> wrote in message
    >news:bj17fm$24j$...
    >> E. Robert Tisdale wrote:
    >> > j wrote:
    >> >> int main(void) { /* This falls in 6.11.6? */

    >
    >Hm, in my original question I didn't have a ``void''.. not sure how that
    >ended up there.

    It's not magic. It's E.R.T.!
    --
    Air is water with holes in it.
     
    Irrwahn Grausewitz, Sep 2, 2003
    #18
  19. On Tue, 2 Sep 2003, j wrote:
    >
    > "Richard Heathfield" <> wrote...
    > > E. Robert Tisdale wrote:

    ^^^^^^^^^^^^^^^^^
    > > > j wrote:
    > > >
    > > >> In section 6.11.6 of c99 it says:
    > > >>
    > > >> "6.11.6 Function declarators
    > > >> 1 The use of function declarators with empty parentheses
    > > >> (not prototype-format parameter type declarators)
    > > >> is an obsolescent feature."


    > > >> int main(void) { /* This falls in 6.11.6? */

    ^^^^
    > >
    > > No, it doesn't. [...]

    >
    > Hm, in my original question I didn't have a ``void''.. not sure how that
    > ended up there.



    This is *exactly* why people should reference the OP's question
    directly, and ignore Tisdale's "contributions." In this case,
    Tisdale modified your question to say something completely
    different, and then two people separately quoted Tisdale's version
    without looking at the real post again. (Don't feed the troll,
    blah blah blah...)

    BTW, Richard, I like that verb "wittering"!

    -Arthur
     
    Arthur J. O'Dwyer, Sep 2, 2003
    #19
  20. Bret

    John Bode Guest

    (Bret) wrote in message news:<>...
    > 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. However the
    > declaration:
    >
    > int main(int argc, char** argv)
    >
    > is common.
    >
    > How does that work out? Shouldn't the compiler complain if you're not
    > doing:
    >
    > int main(int argc, char* argv[])
    >
    > Thanks,
    > Bret



    First of all, the declarator char *argv[] declares argv to be an array
    of pointers to char, not a pointer to an array of char.

    char a[10]; /* a is a 10-element array of char */
    char *a[10]; /* a is a 10-element array of pointer to char */
    char (*a)[10]; /* a is a pointer to a 10-element array of char */
    char *(*a)[10]; /* a is a pointer to a 10-element array of pointer to
    char */

    Secondly, in the context of a formal parameter declaration, char **x
    and char *x[] are understood to mean the same thing. You cannot pass
    a whole array to a function in C (this includes the main() function);
    what actually happens is that a pointer to the first element of the
    array is passed to the function. Therefore, char **x more correctly
    describes what is happening. The [] notation is allowed to imply to
    whomever is reading the program that the argument represents an array
    of something, not just a pointer to an individual element. As far as
    the code is concerned, however, all that's being passed is a pointer
    to a single item (the first element of the array).

    FWIW, this means you can't use sizeof to determine the array size in
    the called function:

    int main (void)
    {
    int x[10];

    /* sizeof x == sizeof int * 10 */
    foo (x); /* actually passes &x[0] */
    return 0;
    }

    void foo (int *x)
    {
    /* sizeof x == sizeof int* */
    }
     
    John Bode, Sep 2, 2003
    #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. David
    Replies:
    10
    Views:
    6,009
    Richard Heathfield
    Sep 15, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,682
    Old Wolf
    Jan 20, 2004
  3. jab3

    char **argv & char *argv[]

    jab3, Dec 4, 2004, in forum: C Programming
    Replies:
    5
    Views:
    679
    Chris Torek
    Dec 8, 2004
  4. lovecreatesbeauty
    Replies:
    1
    Views:
    1,102
    Ian Collins
    May 9, 2006
  5. oogie
    Replies:
    9
    Views:
    663
    Default User
    Nov 18, 2007
Loading...

Share This Page