Array assignment via cast

Discussion in 'C Programming' started by James Mcguire, Jan 18, 2005.

  1. Hi,

    I frequently do non-initialisation type structure assignment via casting:

    e.g.

    struct s{int i,j,k;} mys;
    ....
    mys=(struct s){3,4,5};

    is this possible with an array?
    eg char test[10];

    .... is it possible to assign to test via a cast? is it legal?

    Thanks
     
    James Mcguire, Jan 18, 2005
    #1
    1. Advertising

  2. James Mcguire

    Richard Bos Guest

    James Mcguire <> wrote:

    > I frequently do non-initialisation type structure assignment via casting:


    > mys=(struct s){3,4,5};
    >
    > is this possible with an array?


    No. An array is not a modifiable lvalue, and therefore cannot be
    assigned to. It _can_ be initialised, but that's another part of the
    syntax (using identically-spelled tokens, but that makes no difference).

    Richard
     
    Richard Bos, Jan 18, 2005
    #2
    1. Advertising

  3. On Tue, 18 Jan 2005 13:21:46 +0000, James Mcguire wrote:

    > Hi,
    >
    > I frequently do non-initialisation type structure assignment via casting:
    >
    > e.g.
    >
    > struct s{int i,j,k;} mys;
    > ...
    > mys=(struct s){3,4,5};


    This is not a cast, it is called a compound literal and is a "new" feature
    introduced in C99. If you aren't targetting C99 compilers specifically you
    probably shouldn't use it.

    > is this possible with an array?
    > eg char test[10];


    Arrays are not modifiable lvalues and cannot be assigned to. Probably the
    nearest you can get is something like

    static const char initdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    memcpy(test, initdata, sizeof test);

    Lawrence
     
    Lawrence Kirby, Jan 18, 2005
    #3
  4. James Mcguire

    Chris Torek Guest

    In article <csj2ha$8mc$>
    James Mcguire <> wrote:
    >I frequently do non-initialisation type structure assignment via casting:
    >
    >e.g.
    >
    >struct s{int i,j,k;} mys;
    >...
    >mys=(struct s){3,4,5};


    This is not actually a cast. It is instead a C99-standard form
    called a "compound literal". The syntax for a compound literal
    is:

    ( type-name ) { list-of-values }

    and of course the (, type-name, ) sequence looks exactly like a
    cast. (So why not call it one? Well, because the C99 standard
    calls it something else -- so if you want to communicate with
    C programmers who have read the C99 standard, or a good book
    about C99, presumably you would want to use the same words. Also,
    because you can include the "const" qualifier to good effect.)

    >is this possible with an array?
    >eg char test[10];


    No. You can construct a compound-literal with array type:

    (const char [10]){'a', 'b', 'c'}

    has a pretty similar meaning to:

    "abc\000\000\000\000\000\000"

    Both of these produce an anonymous array object containing 10
    "char"s (note that the string literal has 9 characters in it, a +
    b + c + six copies of \000 + the terminating '\0' that is always
    included for string literals = 10 chars). Both are allowed to
    place the array in read-only storage. The biggest difference
    between the two is that, in a quirk having to do with history, the
    string literal produces the type "array 10 of char" while the
    compound literal has type "array 10 of const char".

    (String-literal-produced arrays really should have "const char",
    but ancient C had no "const" type, and this would have invalidated
    huge quantities of existing code, had the 1989 C standard made
    them "const".)

    The problem is, even having produced an array object, you cannot
    assign it to another array:

    struct s s1, s2;
    ...
    s1 = s2; /* is OK */

    but:

    char a1[10], a2[20];
    ...
    a1 = a2; /* not OK, requires a diagnostic */

    >... is it possible to assign to test via a cast? is it legal?


    Again, it is not a cast, it is a "compound literal"; and no, ordinary
    assignment will not work, just as it does not work with actual
    array objects: the left hand side, a1 in the example above, is not
    a "modifiable lvalue", and the right hand side expression undergoes
    the transform prescribed by The Rule, becoming a pointer value.

    Hence, just as you must memcpy() or strcpy() arrays or strings
    into their target buffers, you must also memcpy() the compound
    literal:

    assert(sizeof a1 <= sizeof a2); /* assumed in memcpy call */
    memcpy(a1, a2, sizeof a1); /* copy the parts of a2 that fit */
    ...
    memcpy(a1, (const char [sizeof a1]){'a', 'b', 'c'}, sizeof a1);

    Note that if you leave out the "const" in a compound literal, the
    compiler is obligated to create a fresh copy whenever the enclosing
    block is entered, in case you take a pointer to the literal and
    then modify it:

    % cat t.c
    #include <stdio.h>

    int main(void) {
    for (int i = 0; i < 3; i++) {
    char *p = (char []) { 'h', 'e', 'l', 'l', 'o', '\0' };
    if (i == 1)
    p[0] = 'j';
    puts(p);
    }
    return 0;
    }
    % cc -std=c99 -O -o t t.c -W -Wall
    % ./t
    hello
    jello
    hello
    %

    This means that the non-"const" version generally invokes an internal
    memcpy() from a "clean" copy each time the block is entered. Using
    the "const" can avoid paying for these copies. (A smart compiler
    will attempt to figure out whether the copy is required, but using
    "const" can save programmer effort too, as the programmer no longer
    has to wonder whether the compound literal ever gets modified.)

    (GCC seems to make a copy every time, even when the compound literal
    uses "const". This probably has to do with "gcc -std=c99" not
    actually implementing C99, but rather something somewhere between
    GNUC and C99. I suspect the GNUC language did not have this special
    "one static copy is OK" property for const-qualified compound
    literals.)
    --
    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, Jan 18, 2005
    #4
  5. Chris Torek <> writes:
    > In article <csj2ha$8mc$>
    > James Mcguire <> wrote:
    >>I frequently do non-initialisation type structure assignment via casting:
    >>
    >>e.g.
    >>
    >>struct s{int i,j,k;} mys;
    >>...
    >>mys=(struct s){3,4,5};

    >
    > This is not actually a cast. It is instead a C99-standard form
    > called a "compound literal". The syntax for a compound literal
    > is:
    >
    > ( type-name ) { list-of-values }
    >
    > and of course the (, type-name, ) sequence looks exactly like a
    > cast. (So why not call it one? Well, because the C99 standard
    > calls it something else -- so if you want to communicate with
    > C programmers who have read the C99 standard, or a good book
    > about C99, presumably you would want to use the same words. Also,
    > because you can include the "const" qualifier to good effect.)

    [...]

    Another good reason not to call it a cast is that it isn't one.

    A cast-expression looks like:

    ( type-name ) expression

    (that's a bit of an over-simplification for reasons that aren't
    relevant to this discussion). The operand has to be an expression,
    which is converted to the named type.

    In a compound literal, the

    { list-of-values }

    is not an expression, and no conversion takes place; instead, the
    type-name tells the compiler what the type of the expression is. The
    only thing it has in common with a cast is that it includes a type
    name in parentheses.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 18, 2005
    #5
  6. rss wrote:
    > Thank you for your incredibly detailed and concise answer.
    >
    > I have a off-topic question; it's becoming apparent that in order to become
    > a more effective C programmer I need to learn more about the standard.
    > What is the best way of perusing this? I took a look at the FAQ and have
    > access to a copy of the C99 standard, but it seems incredibly dense reading
    > that doesn't seem to make much sense to a person mof my experience. Are
    > there any alternative sources of information that would help?
    >
    > Thanks
    >
    >


    This place itself is a definitive resource. Keep reading. ;)

    Regards,
    Jonathan.

    --
    C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
    C Library: http://www.dinkumware.com/refxc.html
    C99 Standard Draft: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/

    "I'm learning to program because then I can write
    programs to do my homework faster." - Andy Anfilofieff
     
    Jonathan Burd, Jan 19, 2005
    #6
  7. James Mcguire

    Flash Gordon Guest

    rss wrote:
    > Thank you for your incredibly detailed and concise answer.
    >
    > I have a off-topic question; it's becoming apparent that in order to become
    > a more effective C programmer I need to learn more about the standard.
    > What is the best way of perusing this? I took a look at the FAQ and have
    > access to a copy of the C99 standard, but it seems incredibly dense reading
    > that doesn't seem to make much sense to a person mof my experience. Are
    > there any alternative sources of information that would help?


    I would suggest getting a copy of The C Programming Language, Second
    Edition, by Kernighan & Ritchie. It is the main reference that I use.
    The only system specific stuff is one chapter called The UNIX System
    Interface which is fairly obvious, the rest is all portable.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Jan 25, 2005
    #7
    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. MSG

    to cast or not to cast malloc ?

    MSG, Feb 6, 2004, in forum: C Programming
    Replies:
    38
    Views:
    1,116
    Dan Pop
    Feb 10, 2004
  2. EvilRix
    Replies:
    8
    Views:
    677
    Martin Dickopp
    Feb 14, 2004
  3. Eric Laberge

    Array assignment via struct

    Eric Laberge, Aug 4, 2005, in forum: C Programming
    Replies:
    36
    Views:
    944
    Dave Thompson
    Aug 14, 2005
  4. Matthias Kaeppler
    Replies:
    2
    Views:
    469
    Victor Bazarov
    Jul 18, 2005
  5. Pavel
    Replies:
    7
    Views:
    561
    Pavel
    Sep 19, 2010
Loading...

Share This Page