Declaration of main()

Discussion in 'C Programming' started by BartC, Mar 29, 2014.

  1. BartC

    BartC Guest

    Cdecl now working again. For this input:

    'explain int main (int argc, char*(*argv)[]);'

    it gives:

    'declare main as function (int, pointer to array of pointer to char)
    returning int'
     
    BartC, Mar 30, 2014
    #21
    1. Advertisements

  2. BartC

    Stefan Ram Guest

    Yes. Decay semantics is usually used. I can define
    a ragged two-dimensional array using decay semantics:

    #include <stdio.h>

    int const a0[ 4 ]={ 1, 2, 3, 4 };
    int const a1[ 4 ]={ 4, 5, 6, 7 };
    int const * const a[ 2 ]={ a0, a1 };

    int main()
    { printf( "first number: %d\n", a[ 0 ][ 0 ]);
    printf( "%zu rows.\n", sizeof a / sizeof 0[ a ]);
    printf( "number of columns is unknown.\n" ); }

    . However, it would also be possible, albeit less common,
    two use proper array-pointer semantics:

    #include <stdio.h>

    int const a0[ 4 ]={ 1, 2, 3, 4 };
    int const a1[ 4 ]={ 4, 5, 6, 7 };
    int const( * const a[ 2 ])[ 4 ]={ &a0, &a1 };

    int main()
    { printf( "first number: %d\n",( *a[ 0 ])[ 0 ]);
    printf( "%zu rows.\n", sizeof a / sizeof 0[ a ]);
    printf( "%zu columns.\n", sizeof *a[ 0 ]/ sizeof 0[ *a[ 0 ]]); }

    . The common definition of the parameters of the
    program-entry function »main« seems to assume decay
    semantics.

    This shows that when a real array-pointer is used, code has
    to be written specifically for this, like for example:
    »( *a[ 0 ])[ 0 ]«.

    It seems be possible to omit the parentheses in »( *a[ 0 ])[ 0 ]«.
    I am not sure why. But one can always write »0[ *a[ 0 ]]«
    without parentheses.
     
    Stefan Ram, Mar 30, 2014
    #22
    1. Advertisements

  3. BartC

    Eric Sosman Guest

    Nitpick: `char* argv[argc+1];'.
     
    Eric Sosman, Mar 30, 2014
    #23
  4. BartC

    BartC Guest

    Which, in most contexts is an array of pointer to char. Only as a parameter
    type (I can't make it work as a return type) does it become a pointer - to
    the start of the array. (Although my cdecl server still told me it was an
    array of char*, even when a parameter type, which sounds like a mistake in
    that program.)

    So C just doesn't like pointers to whole arrays, at least, unbounded ones,
    which makes me wonder why it allows them at all.
    This is a 'discontinuity' in the type-system of C, which I first came across
    a couple of years ago: char[] means an actual array when defining a
    variable, but for a parameter, it's a pointer instead! Similarly with
    char*[] and so on.

    It would have been better, imo, for it to have been more consistent: eg,
    make char[] denote an array in all contexts, but make it an error when used
    for parameter types, rather than require one less "*" for certain parameter
    types.
    Yes; I prefer to keep pointers and arrays separate. This is generally
    supported, but involves using using pointers to incomplete arrays and the
    syntax is a bit of a pain if writing directly in C.
    That's a good way of explaining it.
     
    BartC, Mar 30, 2014
    #24
  5. It's not just passed as a pointer to the first element of the array. It
    *is* a pointer, not an array.

    As a parameter declaration, "char *argv[]" actually means "char **argv".

    The implicit conversion of an array expression to a pointer (in most
    contexts) is a separate language rule.
    That's incorrect. For example, char* (pointer to char) and char (*)[10]
    (pointer to array of 10 char) are distinct and incompatible types.

    It's likely that they have the same representation, and that converting
    from one to the other will do what you expect, but it's not guaranteed.
    What the standard says is that a pointer to an object may be treated as
    a pointer to *the first element of* an array of 1 element.

    [...]
     
    Keith Thompson, Mar 31, 2014
    #25
  6. Right, there's a specific language rule about that.

    N1570 6.7.6.3p7:

    A declaration of a parameter as "array of type" shall be adjusted
    to "qualified pointer to type", where the type qualifiers
    (if any) are those specified within the [ and ] of the array
    type derivation.
    C has no problem with pointers to whole arrays. It's just usually more
    convenient to access an array via a pointer to the element type.

    [...]

    Why can't you just define main() using one of the two standard forms?
     
    Keith Thompson, Mar 31, 2014
    #26
  7. BartC

    BartC Guest

    When I tried g++ (which I assume is a C++ compiler), it doesn't seem to
    allow such pointers to unbounded arrays at all. I was actually thinking of
    just using void* for /any/ pointer parameter, and just sticking the right
    cast in as needed.

    Then most such problems should disappear (except for main()).
    The code for main() is created by a source-to-source translator which does
    not treat "main" any differently.

    I am now using the equivalent of "char **" in the source; there are still
    some issues, but at least the result compiles.

    (However, I am trying to compile my programs with six different C compilers,
    and there are plenty more annoying and often inexplicable problems to
    overcome.)
     
    BartC, Mar 31, 2014
    #27
  8. Pointers to *incomplete* arrays (defined with empty []) might be a
    problem in some cases; I've rarely used them myself. But this:

    #include <stdio.h>
    int main(void) {
    char arr[] = "hello";
    char (*p)[] = &arr;
    printf("*p = %s\n", *p);
    }

    compiles and executes with no problem using either gcc or clang.

    It doesn't compile with g++. But g++ is a compiler for *a different
    language*. If you have questions about pointers to incomplete array
    types in C++, I suggest posting in comp.lang.c++.
    Well there's your problem. The C language restricts the manner in which
    "main" can be defined. You can't just translate an arbitrary "main"
    function in some other language into C and expect a C compiler to accept
    it, unless the C "main" follows C's rules.

    You can't just generate C. You need to generate *valid* C.
    So far, it seems that you're having problems with the fact that C
    compilers enforce the requirements of the C language. In some cases
    (like permitted definitions for "main"), you're seeing different
    behaviors with different compilers because the C standard permits
    variations.

    Feel free to ask about any specific problems you're having (but first I
    suggest reading the standard; you might be able to solve some of them
    yourself).
     
    Keith Thompson, Mar 31, 2014
    #28
  9. There are certain things you can do with a pointer to unbounded arrays;
    for example, you can have 'f(int (*a)[], size_t n)' that loops from
    (*a)[0] through (*a)[n-1]. (A much more natural thing would be
    'f(int a[], size_t n)' that loops from a[0] through a[n-1], of course.)

    However, you cannot do a+1, a[1], a++ or sizeof(a).

    So there seems to be little, if any, that you gain from having
    'int (*a)[]' instead of 'int a[]', and that maybe explains why you see
    pointers to unbounded arrays so rarely.
    Another (unfortunate) bit of history; you can find the meaning of [N] and
    [] in NB (for "new B") at <http://cm.bell-labs.com/who/dmr/chist.html>.
     
    Seungbeom Kim, Apr 1, 2014
    #29
  10. The heart of the language is that you can declare a buffer with the
    square brackets, pass it to a subroutine either as a whole or in chunks
    using pointers, then access it as a random-access array in that subroutine
    using the square brackets again.
    malloc() can conceptually, and in small systems is often actually, built on
    top of that, with a big buffer somewhere you allocate out of. Dynamic memory
    is of course crucial to allow functions to scale to arbitrary-sized input.

    That's basically C. Declare buffers, take pointers to them, and shuffle
    the contents around in memory.
     
    Malcolm McLean, Apr 1, 2014
    #30
  11. BartC

    Tim Rentsch Guest

    In C, except for variable length arrays, types are purely a
    static compile-time property of various syntatic units, notably
    expressions and some declared identifiers. Any type that is
    incomplete at compile time is equally incomplete at run time.

    The C standard does define a notion called effective type, which
    is a run-time property. However, effective type is not the same
    as type, and furthermore it is rarely the case that there is an
    effective type that is an array type. Memory that has been
    malloc()'ed, for example, and accessed as an array typically
    never acquires an effective type of a whole, but only at the
    level of individual elements.
     
    Tim Rentsch, Apr 15, 2014
    #31
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.