Re: what does global char x[][444] mean?

Discussion in 'C Programming' started by Niu Xiao, Oct 21, 2005.

  1. Niu Xiao

    Niu Xiao Guest

    Cheney Stallman wrote:
    > When I define local variable as char x[][444], compile does not allow.
    > However, I define this as global variable. compile will be happy.
    > code snip as following:
    > char x[][444];
    > int main()
    > {
    > sizeof(x);
    > return 0;
    > }
    > but, when I compile it. the compiler complain sizeof error.
    > why this occur?
    >
    > Any reply is appreciated.
    >
    >


    Neither global nor local is allowed. When you write char x[][444] as
    global definition, some compiler treat it as char x[1][444], but it's
    non-standard.

    You can only use it as global declaration or function parameter:

    /* global */
    extern char x[][444];

    /* function parameter */
    void foo(char x[][444]); /* or void foo(char (*x)[444]); */
    Niu Xiao, Oct 21, 2005
    #1
    1. Advertising

  2. Not exactly.

    There are three test program as following.
    Note: I using gcc to compile test program.
    1. the follow program comiplie failed:
    // error: array size missing in 'x'
    int main()
    {
    char x[][444];
    return 0;
    }

    2. the follow program compile OK.
    char x[][444];
    int main()
    {
    return 0;
    }


    3. the follow program comiplie failed:
    // error: invalid application of `sizeof' to
    // incomplete type `({anonymous})'
    char x[][444];
    int main()
    {
    sizeof(x);
    return 0;
    }

    Through the test, I think here char x[][444] is more likely
    a declare, thoung it does not `extern', not a define.
    Can any expert give some sugguestion.




    "Niu Xiao" <> Wrote:djb5fu$ldt$...
    >
    > Neither global nor local is allowed. When you write char x[][444] as
    > global definition, some compiler treat it as char x[1][444], but it's
    > non-standard.
    >
    > You can only use it as global declaration or function parameter:
    >
    > /* global */
    > extern char x[][444];
    >
    > /* function parameter */
    > void foo(char x[][444]); /* or void foo(char (*x)[444]); */
    Cheney Stallman, Oct 22, 2005
    #2
    1. Advertising

  3. Niu Xiao

    Niu Xiao Guest

    Cheney Stallman wrote:
    > Not exactly.
    >
    > There are three test program as following.
    > Note: I using gcc to compile test program.
    > 1. the follow program comiplie failed:
    > // error: array size missing in 'x'
    > int main()
    > {
    > char x[][444];
    > return 0;
    > }
    >
    > 2. the follow program compile OK.
    > char x[][444];
    > int main()
    > {
    > return 0;
    > }
    >


    My compiler (gcc 3.3.5) said:
    a.c:8: warning: array `x' assumed to have one element

    >
    > 3. the follow program comiplie failed:
    > // error: invalid application of `sizeof' to
    > // incomplete type `({anonymous})'
    > char x[][444];
    > int main()
    > {
    > sizeof(x);
    > return 0;
    > }
    >
    > Through the test, I think here char x[][444] is more likely
    > a declare, thoung it does not `extern', not a define.
    > Can any expert give some sugguestion.
    >


    No, any global declaration without 'extern' is definition.
    Arrays in C are always static, so you can't define an array without
    specifying its size.

    >
    >
    >
    > "Niu Xiao" <> Wrote:djb5fu$ldt$...
    >
    >>Neither global nor local is allowed. When you write char x[][444] as
    >>global definition, some compiler treat it as char x[1][444], but it's
    >>non-standard.
    >>
    >>You can only use it as global declaration or function parameter:
    >>
    >>/* global */
    >>extern char x[][444];
    >>
    >>/* function parameter */
    >>void foo(char x[][444]); /* or void foo(char (*x)[444]); */

    >
    >
    >
    Niu Xiao, Oct 22, 2005
    #3
  4. Niu Xiao

    Guest

    may be you can use the "sizeof" to try to check its size .
    Gcc compiler will tell you the size.
    then u can easy to treat it
    , Oct 22, 2005
    #4
  5. My gcc version is 3.4.4.
    I think the `extern' keyword only is explicit keyword. `extern' can be
    omited.

    The following program can compile under VC7.1/VC6/gcc-3.4.4
    char x[][444]; // I think here x is a declare?
    char x[][444] = {{0}}; // here x is real definition?
    int main()
    {
    return 0;
    }



    "Niu Xiao" <> wrote:djcic2$hvo$...
    >
    > My compiler (gcc 3.3.5) said:
    > a.c:8: warning: array `x' assumed to have one element
    >
    >
    > No, any global declaration without 'extern' is definition.
    > Arrays in C are always static, so you can't define an array without
    > specifying its size.
    >

    If you think it's declare, then everything goes well.

    >>
    >>>Neither global nor local is allowed. When you write char x[][444] as
    >>>global definition, some compiler treat it as char x[1][444], but it's
    >>>non-standard.
    >>>
    >>>You can only use it as global declaration or function parameter:
    >>>
    >>>/* global */
    >>>extern char x[][444];
    >>>
    >>>/* function parameter */
    >>>void foo(char x[][444]); /* or void foo(char (*x)[444]); */

    >>
    >>
    >>

    >
    >
    Cheney Stallman, Oct 22, 2005
    #5
  6. Niu Xiao

    Chris Torek Guest

    In an article that is not on my server (fortunately Niu Xiao
    quoted it), Cheney Stallman wrote:
    >> When I define local variable as char x[][444], compile does not allow.
    >> However, I define this as global variable. compile will be happy.
    >> code snip as following:
    >> char x[][444];
    >> int main()
    >> {
    >> sizeof(x);
    >> return 0;
    >> }
    >> but, when I compile it. the compiler complain sizeof error.
    >> why this occur?


    The above is indeed invalid (and requires a diagnostic), but if you
    remove the "sizeof(x)" expression, it is valid Standard C.

    In article <djb5fu$ldt$> Niu Xiao <> wrote:
    >Neither global nor local is allowed. When you write char x[][444] as
    >global definition, some compiler treat it as char x[1][444], but it's
    >non-standard.


    No, it is in fact standard.

    C has the notion of an "incomplete type". The most familiar version
    of this, for most C programmers, should be deliberately-incomplete
    "struct" names:

    struct foo;
    struct foo *make_new_foo(void);
    void operate_on_foo(struct foo *);
    void destroy_foo(struct foo *);

    void f(void) {
    struct foo *p;

    p = make_new_foo();
    operate_on_foo(p);
    destroy_foo(p);
    }

    This is valid C code, and allows function f() to create, operate
    on, and destroy an object of type "foo" -- remember that C spells
    "user defined abstract data type" using the word "struct" -- without
    ever describing what is inside the type. It is difficult for f()
    to "cheat" and write on, say, p->count, because f() does not know
    whether a p->count even exists, much less what its offset in the
    structure might be.

    As it happens, however, an array whose size is unknown is also
    an incomplete type. This is really only useful when you use the
    "extern" keyword to announce that an array exists somewhere,
    but the definition is elsewhere:

    extern int a[]; /* a is an array of some unknown number of "int"s */

    Attempting to use sizeof on an incomplete type is an error that
    requires a diagnostic:

    void g(void) {
    sizeof(struct foo); /* error, diagnostic required */
    sizeof a; /* error, diagnostic required */
    }

    (a single diagnostic suffices for this, although most decent
    compilers will produce two here).

    If you omit the "extern" keyword, though, you get a "tentative
    definition" for any variable you have not initialized:

    int var7; /* tentative definition */
    int var123 = 45; /* definition */
    int var92[]; /* also a tentative definition! */

    Here "var7" is "tentatively defined" -- and so is "var92". If,
    upon reaching the end of the "translation unit" (source file with
    #include lines expanded, more or less), no other definition has
    overridden them, each tentative definition is replaced with an
    actual definition:

    /* end of translation unit */
    /* compiler now "pretends" it sees: */
    int var7 = { 0 };
    int var92[] = { 0 };

    (note that braces around the initializer for var7 are permitted,
    while braces around the initializer-list for var92 are required;
    I use them for var7 just to make the two lines symmetric).

    The definition for var92 supplies the size of the array: there
    is a single initializer, so the array has one element. This
    also completes the type: var92 has type "array 1 of int".

    Arrays of size 1 are a bit peculiar. I had a friend who was fond
    of using them instead of simple objects, though, just to avoid
    writing "&var":

    #include <time.h>

    void somefunc(void) {
    time_t now[1];
    char *s;

    if (time(now) == (time_t)-1) ... handle error ...
    s = ctime(now);
    printf("%s", s); /* note, s includes the newline */
    }

    With some non-Standard (but fairly common) functions, one winds
    up with code like this:

    struct stat st[1];

    if (stat(filename, st)) ... handle error ...
    ... work with st->st_size, etc ...

    I prefer to write:

    struct stat st;

    if (stat(filename, &st)) ...
    ... work with st.st_size, etc ...

    myself, but this technique does work.

    >You can only use it as global declaration or function parameter:
    >
    >/* global */
    >extern char x[][444];


    I certainly consider this better style.

    >/* function parameter */
    >void foo(char x[][444]); /* or void foo(char (*x)[444]); */


    The second declaration is, in my opinion, "better" because it tells
    you the correct type for x -- it is not "array ? of array 444 of
    char", where the question-mark indicates that the number is unknown
    so that the size is complete, but rather "pointer to array 444 of
    char", due to C's type-rewriting rules for formal parameters.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Oct 22, 2005
    #6
  7. Niu Xiao

    Tim Rentsch Guest

    Chris Torek <> writes:

    > In an article that is not on my server (fortunately Niu Xiao
    > quoted it), Cheney Stallman wrote:
    >
    > >/* function parameter */
    > >void foo(char x[][444]); /* or void foo(char (*x)[444]); */

    >
    > The second declaration is, in my opinion, "better" because it tells
    > you the correct type for x -- it is not "array ? of array 444 of
    > char", where the question-mark indicates that the number is unknown
    > so that the size is complete, but rather "pointer to array 444 of
    > char", due to C's type-rewriting rules for formal parameters.


    I find this statement somewhat surprising. Normally I expect
    that different syntaxes for pointer parameters will be used
    depending on how the parameter identifier is used within the
    function (and perhaps depending on what sorts of arguments are
    expected on typical calls). If the parameter identifier is used
    in a pointer-like fashion, declare it using the *x syntax; if
    the parameter is used in an array-like fashion, declare it using
    the x[] syntax. The expectations for the two scenarios are
    different, and there is some value in distinguishing them,
    which the different syntax choices can provide.

    I'm not voicing a disagreement, just a surprise. Is there more
    to the rationale here than just the statement that the pointer
    type is the "correct type"?
    Tim Rentsch, Oct 26, 2005
    #7
  8. Tim Rentsch wrote:

    > Chris Torek <> writes:
    >
    >> In an article that is not on my server (fortunately Niu Xiao
    >> quoted it), Cheney Stallman wrote:
    >>
    >> >/* function parameter */
    >> >void foo(char x[][444]); /* or void foo(char (*x)[444]); */

    >>
    >> The second declaration is, in my opinion, "better" because it tells
    >> you the correct type for x -- it is not "array ? of array 444 of
    >> char", where the question-mark indicates that the number is unknown
    >> so that the size is complete, but rather "pointer to array 444 of
    >> char", due to C's type-rewriting rules for formal parameters.

    >
    > I find this statement somewhat surprising.


    [ ... ]

    > I'm not voicing a disagreement, just a surprise. Is there more
    > to the rationale here than just the statement that the pointer
    > type is the "correct type"?


    If the array notation is used, one might be tempted to use sizeof on the
    object, even when one should know better. With the second declaration, such
    impure thoughts are much less likely to arise.


    Christian
    Christian Kandeler, Oct 27, 2005
    #8
  9. Niu Xiao

    Tim Rentsch Guest

    Christian Kandeler <_invalid> writes:

    > Tim Rentsch wrote:
    >
    > > Chris Torek <> writes:
    > >
    > >> In an article that is not on my server (fortunately Niu Xiao
    > >> quoted it), Cheney Stallman wrote:
    > >>
    > >> >/* function parameter */
    > >> >void foo(char x[][444]); /* or void foo(char (*x)[444]); */
    > >>
    > >> The second declaration is, in my opinion, "better" because it tells
    > >> you the correct type for x -- it is not "array ? of array 444 of
    > >> char", where the question-mark indicates that the number is unknown
    > >> so that the size is complete, but rather "pointer to array 444 of
    > >> char", due to C's type-rewriting rules for formal parameters.

    > >
    > > I find this statement somewhat surprising.

    >
    > [ ... ]
    >
    > > I'm not voicing a disagreement, just a surprise. Is there more
    > > to the rationale here than just the statement that the pointer
    > > type is the "correct type"?

    >
    > If the array notation is used, one might be tempted to use sizeof on the
    > object, even when one should know better. With the second declaration, such
    > impure thoughts are much less likely to arise.


    My conclusion would be just the opposite. The array-form declaration
    looks like an incomplete type, and sizeof can't be used on incomplete
    types.

    Conversely, using the array-form syntax could be used to provide
    information that would help program safety - for example, a compiler
    could provide a warning switch for using sizeof on a parameter
    declared using the array-form syntax. It seems far more likely to
    have sizeof applied wrongly through indirect means (such as the well
    known "number of array elements" macro) than through direct
    application. Using the array-form syntax could help with that.
    Tim Rentsch, Oct 27, 2005
    #9
  10. Niu Xiao

    pete Guest

    Niu Xiao wrote:

    > Arrays in C are always static, so you can't define an array without
    > specifying its size.


    You can't define an array without specifying its size,
    that's true, but there are such things as automatic arrays.

    --
    pete
    pete, Oct 27, 2005
    #10
  11. Niu Xiao

    Chris Torek Guest

    [regarding either:
    void foo(char x[][444]);
    or:
    void foo(char (*x)[444]);
    ]

    >Chris Torek <> writes:
    >> The second declaration is, in my opinion, "better" because it tells
    >> you the correct type for x -- it is not "array ? of array 444 of
    >> char", where the question-mark indicates that the number is unknown
    >> so that the size is complete, but rather "pointer to array 444 of
    >> char", due to C's type-rewriting rules for formal parameters.


    In article <>
    Tim Rentsch <> wrote (and I apologize for
    quoting the whole thing, but I can find no text to delete here):
    >I find this statement somewhat surprising. Normally I expect
    >that different syntaxes for pointer parameters will be used
    >depending on how the parameter identifier is used within the
    >function (and perhaps depending on what sorts of arguments are
    >expected on typical calls). If the parameter identifier is used
    >in a pointer-like fashion, declare it using the *x syntax; if
    >the parameter is used in an array-like fashion, declare it using
    >the x[] syntax. The expectations for the two scenarios are
    >different, and there is some value in distinguishing them,
    >which the different syntax choices can provide.
    >
    >I'm not voicing a disagreement, just a surprise. Is there more
    >to the rationale here than just the statement that the pointer
    >type is the "correct type"?


    That really is pretty much it. But I will also add that, while it
    is possible to use array vs pointer notation in prototype declarations
    (and function definitions, for that matter) as a sort of "usage
    documentation", as you note, I find that it is not used that way,
    at least not with any consistency, in most of the code I deal with.
    Not only does a lot of code use, e.g.:

    void f(T *p /* and possibly additional parameters */) {
    ... occurrences of p for some appropriate i ...
    }

    but some even uses:

    void g(T arr[]) {
    ... occurrences of arr++ ...
    }

    In my experience, the latter is fairly rare (which I think is
    a good thing -- the rarity, that is).

    I have also seen a number of C programmers express surprise that
    the latter works, and that in code like:

    void h(size_t n, T a[N]) {
    printf("%lu\n", (unsigned long)sizeof a);
    }

    the size printed is sizeof(T *) and not sizeof(T [N]). This tells
    me that these programmers believe (at least initially) that "a"
    here has the type "array N of T", rather than "pointer to T". I
    think they are better-served by writing "T *a". If documentation
    to the effect that "a" should be the address of the first of N
    objects of type T, one can always use C's documentation facility:

    /*
    * The function h() operates on n items of type T, so pass
    * the address of the first one, e.g.:
    * T arr[N];
    * h(N, arr);
    */
    void h(size_t n, T *a) {
    ... code ...
    }
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Oct 28, 2005
    #11
  12. <OT, absolutely>

    Chris Torek wrote:
    <snipped>
    It was some 2 years ago that i started closely following your posts on
    clc. With my C programming skills being just knee high, i have to
    re-read your posts again and again to actually make out the point you
    are trying to make. And at the end of it, its enlightenment for me.
    Seriously.

    I am reminded of a request by another clc regular more than a decade
    ago. He was interested to know if you ever considered writing a book on
    C programming. To which you had replied citing your reasons for your
    decision. I wish you had considered writing a book.

    Anyway, i collect your posts and have a nice collection of some of the
    finest mails explaining some basic C fundamentals which most of us
    newcomers stumble upon.. and which form a topics for discussion when me
    and my friends meet.

    The thing that helps me most is what you had once pointed out, "most
    problems have a lot of unncessary details. Big thing lies in removing
    the unwanted stuff and thinking about the actual problem." I realise
    that i missed the most basics of problem solving..

    Regards,
    Prafulla Harpanhalli

    </OT, absolutely>
    Prafulla Harpanhalli, Oct 30, 2005
    #12
  13. Niu Xiao

    Greg Comeau Guest

    In article <>,
    Prafulla Harpanhalli <> wrote:
    >The thing that helps me most is what you had once pointed out, "most
    >problems have a lot of unncessary details. Big thing lies in removing
    >the unwanted stuff and thinking about the actual problem." I realise
    >that i missed the most basics of problem solving..


    "Perfection is achieved, not when there is nothing more to add,
    but when there is nothing left to take away." - Antoine de Saint Exupery
    --
    Greg Comeau / Celebrating 20 years of Comeauity!
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
    Greg Comeau, Oct 30, 2005
    #13
  14. Niu Xiao

    Tim Rentsch Guest

    Chris Torek <> writes:

    > [regarding either:
    > void foo(char x[][444]);
    > or:
    > void foo(char (*x)[444]);
    > ]
    >
    > >Chris Torek <> writes:
    > >> The second declaration is, in my opinion, "better" because it tells
    > >> you the correct type for x -- it is not "array ? of array 444 of
    > >> char", where the question-mark indicates that the number is unknown
    > >> so that the size is complete, but rather "pointer to array 444 of
    > >> char", due to C's type-rewriting rules for formal parameters.

    >
    > In article <>
    > Tim Rentsch <> wrote [excerpt follows]
    > >
    > >I'm not voicing a disagreement, just a surprise. Is there more
    > >to the rationale here than just the statement that the pointer
    > >type is the "correct type"?

    >
    > That really is pretty much it. But I will also add that, while it
    > is possible to use array vs pointer notation in prototype declarations
    > (and function definitions, for that matter) as a sort of "usage
    > documentation", as you note, I find that it is not used that way,
    > at least not with any consistency, in most of the code I deal with.
    >
    > [Summary: code that
    > uses p for parameter declared T *p;
    > doing arr++ for parameter declared T arr[];
    > doing sizeof a for parameter declared T a[N], perhaps expecting
    > the result N * sizeof(T) but getting sizeof(T*)
    > ]


    That explanation helps me understand the earlier statement
    (and the motivations for it) much better. Thank you.

    All of the examples are patterns that could be identified
    by a compiler and flagged as warnings. Another one is
    mixing *p and p, for any parameter variable p, in a
    single function body. Or, using *p for a parameter
    declared T p[]. It would be interesting to add these
    warnings in the context of a particular development team
    and see what the effects are, both on the code and on the
    attitudes of the developers. Personally I'd like to see
    compilation flags for warning on these patterns added to
    existing compilers. (I'm not advocating they be enabled
    by default, only that they could be if someone wanted to.)

    Part of the reason for my surprise is that the response
    seems somewhat defeatist. Paraphrasing (perhaps slightly
    unfairly), "If you use the pointer-in-array-clothing syntax
    then you (or your fellow programmers) are going to be
    confused or do something confusing, so never use that
    syntax." Maybe it's the optimist in me, but I'd like to
    think it's better to educate more about what the rules
    really say, and try to encourage deeper understanding.
    Taking the other tack, to convey the message "stay away
    from this part of the language because it's dangerous and
    confusing", seems like it might become a self-fulfilling
    prophecy. (I should add that this view is just personal
    opinion, not something I've ever tried to validate with an
    actual development team.)
    Tim Rentsch, Nov 1, 2005
    #14
    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. Arnold Peters
    Replies:
    1
    Views:
    427
    Paul Lutus
    Oct 20, 2004
  2. John Dean
    Replies:
    5
    Views:
    1,184
    Hans Nowak
    Sep 9, 2003
  3. G Patel
    Replies:
    6
    Views:
    994
    Karthik Kumar
    Jan 24, 2005
  4. lovecreatesbeauty
    Replies:
    1
    Views:
    1,043
    Ian Collins
    May 9, 2006
  5. C Barrington-Leigh
    Replies:
    1
    Views:
    1,196
    Tim Leslie
    Sep 10, 2010
Loading...

Share This Page