Struct assignment

Discussion in 'C Programming' started by Grey Alien, Jun 30, 2007.

  1. Grey Alien

    Grey Alien Guest

    If I have the ff struct:

    struct A
    {
    unsigned int i;
    char s[LONG_ENOUGH];
    } a, b;


    And use them in code like this:

    a.i = 42 ;
    strcpy(a.s,"test");

    b.i = 100 ;

    b = a ;

    at this point, a (bitwise?) copy of a is made to b. Question is:

    1). is b.s now ptr to a.s ? (I think so)
    If so, what happens if for instance variable 'a' goes out of scope (?)

    2). Does the compiler generate an implicit "memcpy" or "memmove" behind
    the scenes when it sees an assignment like this (to avoid dangling ptrs)?
     
    Grey Alien, Jun 30, 2007
    #1
    1. Advertising

  2. "Grey Alien" <> wrote in message
    news:...
    > If I have the ff struct:
    >
    > struct A
    > {
    > unsigned int i;
    > char s[LONG_ENOUGH];
    > } a, b;
    >
    >
    > And use them in code like this:
    >
    > a.i = 42 ;
    > strcpy(a.s,"test");
    >
    > b.i = 100 ;
    >
    > b = a ;
    >
    > at this point, a (bitwise?) copy of a is made to b. Question is:
    >
    > 1). is b.s now ptr to a.s ? (I think so)
    > If so, what happens if for instance variable 'a' goes out of scope (?)
    >
    > 2). Does the compiler generate an implicit "memcpy" or "memmove" behind
    > the scenes when it sees an assignment like this (to avoid dangling ptrs)?
    >

    The answer is 2. A structure assignment will cause a call to memcpy to be
    made, or equivalent code emitted if the structure is small enough to make
    this wasteful and the compiler is clever.
    However if structures contain pointers then the values of the pointers are
    overwritten. So you have to be extremely careful not to orphan memory or
    create peculiar bugs with aliases.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
     
    Malcolm McLean, Jun 30, 2007
    #2
    1. Advertising

  3. Grey Alien

    Flash Gordon Guest

    Grey Alien wrote, On 30/06/07 17:43:
    > If I have the ff struct:
    >
    > struct A
    > {
    > unsigned int i;
    > char s[LONG_ENOUGH];
    > } a, b;
    >
    >
    > And use them in code like this:
    >
    > a.i = 42 ;
    > strcpy(a.s,"test");
    >
    > b.i = 100 ;
    >
    > b = a ;
    >
    > at this point, a (bitwise?) copy of a is made to b.


    It is not a bitwise copy, it is a copy of all the elements in the struct.

    > Question is:
    >
    > 1). is b.s now ptr to a.s ? (I think so)


    Since b.s was not defined as a pointer, what makes you think an
    assignment could magically transform it from being an array in to being
    a pointer? You need to read section 6 of the comp.lang.c FAQ at
    http://c-faq.com/ specifically the questions dealing with whether
    pointers and arrays are the same thing.

    > If so, what happens if for instance variable 'a' goes out of scope (?)
    >
    > 2). Does the compiler generate an implicit "memcpy" or "memmove" behind
    > the scenes when it sees an assignment like this (to avoid dangling ptrs)?


    It is very rare for C to do things behind your back. Had there been
    pointers in your struct (which there were not) then after the assignment
    they would point to the same place as they point in the original struct,
    and when that place is no longer valid (an automatic that goes out of
    scope, for example) the pointers are no longer valid.
    --
    Flash Gordon
     
    Flash Gordon, Jun 30, 2007
    #3
  4. On Jun 30, 9:43 am, Grey Alien <> wrote:
    > If I have the ff struct:
    >
    > struct A
    > {
    > unsigned int i;
    > char s[LONG_ENOUGH];
    >
    > } a, b;
    >
    > And use them in code like this:
    >
    > a.i = 42 ;
    > strcpy(a.s,"test");
    >
    > b.i = 100 ;
    >
    > b = a ;
    >
    > at this point, a (bitwise?) copy of a is made to b.
    > Question is:
    >
    > 1). is b.s now ptr to a.s ? (I think so)


    I think you are confusing arrays and pointers. Since a.s is an array,
    a.s[0] to a.s[LONG_ENOUGH-1] are actually stored in the structure and
    are copied by the assignment.

    If a.s were just a pointer to memory allocated elsewhere the
    assignment would just copy the pointer.

    > 2). Does the compiler generate an implicit "memcpy"
    > or "memmove" behind the scenes when it sees an
    > assignment like this (to avoid dangling ptrs)?


    There is an explicit copy since a.s is an array. If a.s
    were a pointer there would not be an implicit copy, and
    Bad Things such as dangling pointers could result.

    -thomas
     
    Thomas Lumley, Jun 30, 2007
    #4
  5. Grey Alien

    Serve Lau Guest

    "Flash Gordon" <> wrote in message
    news:-gordon.me.uk...
    > Grey Alien wrote, On 30/06/07 17:43:
    >> If I have the ff struct:
    >>
    >> struct A
    >> {
    >> unsigned int i;
    >> char s[LONG_ENOUGH];
    >> } a, b;
    >>
    >>
    >> And use them in code like this:
    >>
    >> a.i = 42 ;
    >> strcpy(a.s,"test");
    >>
    >> b.i = 100 ;
    >>
    >> b = a ;
    >>
    >> at this point, a (bitwise?) copy of a is made to b.

    >
    > It is not a bitwise copy, it is a copy of all the elements in the struct.
    >
    > > Question is:
    >>
    >> 1). is b.s now ptr to a.s ? (I think so)

    >
    > Since b.s was not defined as a pointer, what makes you think an assignment
    > could magically transform it from being an array in to being a pointer?
    > You need to read section 6 of the comp.lang.c FAQ at http://c-faq.com/
    > specifically the questions dealing with whether pointers and arrays are
    > the same thing.


    Its easy to see where the confusion comes from. There are situations where
    pointers degenerate into pointers , the OP probably had that in mind
     
    Serve Lau, Jun 30, 2007
    #5
  6. Grey Alien

    Flash Gordon Guest

    Serve Lau wrote, On 30/06/07 19:53:
    > "Flash Gordon" <> wrote in message
    > news:-gordon.me.uk...
    >> Grey Alien wrote, On 30/06/07 17:43:


    <snip>

    >>> 1). is b.s now ptr to a.s ? (I think so)

    >> Since b.s was not defined as a pointer, what makes you think an assignment
    >> could magically transform it from being an array in to being a pointer?
    >> You need to read section 6 of the comp.lang.c FAQ at http://c-faq.com/
    >> specifically the questions dealing with whether pointers and arrays are
    >> the same thing.

    >
    > Its easy to see where the confusion comes from. There are situations where
    > pointers degenerate into pointers , the OP probably had that in mind


    In my opinion it is only easy to confuse arrays and pointers if it is
    badly taught. If arrays and pointers are taught as fundamentally
    different concepts and *then* the way array names degenerate to pointers
    to the first element is explained there will not be anything like the
    problems. In one-to-one sessions I've been able to explain the basics of
    arrays pointers to non-computer people in minutes (I needed to so I
    could explain approximately what was the cause of a problem), although I
    did not go on to how things are done in C.
    --
    Flash Gordon
     
    Flash Gordon, Jun 30, 2007
    #6
  7. Serve Lau said:

    <snip>

    > Its easy to see where the confusion comes from. There are situations
    > where pointers degenerate into pointers ,


    Pointers always degenerate into pointers.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Jun 30, 2007
    #7
  8. Flash Gordon <> writes:
    > Grey Alien wrote, On 30/06/07 17:43:
    >> If I have the ff struct:
    >> struct A
    >> {
    >> unsigned int i;
    >> char s[LONG_ENOUGH];
    >> } a, b;
    >> And use them in code like this:
    >> a.i = 42 ;
    >> strcpy(a.s,"test");
    >> b.i = 100 ;
    >> b = a ;
    >> at this point, a (bitwise?) copy of a is made to b.

    >
    > It is not a bitwise copy, it is a copy of all the elements in the struct.


    Yes -- and that can be, and commonly is, implemented as a bitwise copy
    of the struct.

    Suppose there's a gap between the members "i" and "s". After the
    assignment "b = a;", the gaps in "a" and "b" may or may not have the
    same contents. The assignment can be done either as a bitwise copy or
    by copying the members one-by-one, leaving any gaps alone.

    99% of the type, this doesn't matter because you're never going to
    look at what's in the gaps anyway.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 30, 2007
    #8
  9. Grey Alien

    Flash Gordon Guest

    Richard Heathfield wrote, On 30/06/07 20:56:
    > Serve Lau said:
    >
    > <snip>
    >
    >> Its easy to see where the confusion comes from. There are situations
    >> where pointers degenerate into pointers ,

    >
    > Pointers always degenerate into pointers.


    No they don't, they stay as pointers ;-)

    Knowing what Serve Lau must have intended I read it as "where arrays
    degenerate...".
    --
    Flash Gordon
     
    Flash Gordon, Jun 30, 2007
    #9
  10. Grey Alien

    Flash Gordon Guest

    Keith Thompson wrote, On 30/06/07 21:30:
    > Flash Gordon <> writes:
    >> Grey Alien wrote, On 30/06/07 17:43:
    >>> If I have the ff struct:
    >>> struct A
    >>> {
    >>> unsigned int i;
    >>> char s[LONG_ENOUGH];
    >>> } a, b;
    >>> And use them in code like this:
    >>> a.i = 42 ;
    >>> strcpy(a.s,"test");
    >>> b.i = 100 ;
    >>> b = a ;
    >>> at this point, a (bitwise?) copy of a is made to b.

    >> It is not a bitwise copy, it is a copy of all the elements in the struct.

    >
    > Yes -- and that can be, and commonly is, implemented as a bitwise copy
    > of the struct.
    >
    > Suppose there's a gap between the members "i" and "s". After the
    > assignment "b = a;", the gaps in "a" and "b" may or may not have the
    > same contents. The assignment can be done either as a bitwise copy or
    > by copying the members one-by-one, leaving any gaps alone.
    >
    > 99% of the type, this doesn't matter because you're never going to
    > look at what's in the gaps anyway.


    Where there are multiple representations for the same value the
    representation could change. It is important for the OP to know this
    IMHO so that s/he does not assume that memcmp can be used safely.
    --
    Flash Gordon
     
    Flash Gordon, Jun 30, 2007
    #10
  11. Flash Gordon said:

    > Richard Heathfield wrote, On 30/06/07 20:56:
    >> Serve Lau said:
    >>
    >> <snip>
    >>
    >>> Its easy to see where the confusion comes from. There are situations
    >>> where pointers degenerate into pointers ,

    >>
    >> Pointers always degenerate into pointers.

    >
    > No they don't, they stay as pointers ;-)
    >
    > Knowing what Serve Lau must have intended I read it as "where arrays
    > degenerate...".


    I know. Actually, arrays never actually do that. We often say they do,
    but we're just being lazy. What we really mean is that the name of an
    array, when used in an expression, is often (indeed, *usually*) treated
    as if it were a pointer to the array's first element. The array itself
    never "degenerates" (or "decays", as it is usually put) at all.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Jun 30, 2007
    #11
  12. Grey Alien

    Army1987 Guest

    "Grey Alien" <> ha scritto nel messaggio news:...
    > If I have the ff struct:
    >
    > struct A
    > {
    > unsigned int i;
    > char s[LONG_ENOUGH];
    > } a, b;
    >
    >
    > And use them in code like this:
    >
    > a.i = 42 ;
    > strcpy(a.s,"test");
    >
    > b.i = 100 ;
    >
    > b = a ;
    >
    > at this point, a (bitwise?) copy of a is made to b. Question is:
    >
    > 1). is b.s now ptr to a.s ? (I think so)

    No, since it is an array, not a pointer.

    > If so, what happens if for instance variable 'a' goes out of scope (?)
    >
    > 2). Does the compiler generate an implicit "memcpy" or "memmove" behind the scenes when it sees an assignment like this?

    It could, but it needn't. For example, padding bits needn't be
    copied.
     
    Army1987, Jul 1, 2007
    #12
  13. Grey Alien

    Eric Sosman Guest

    Malcolm McLean wrote On 06/30/07 13:05,:
    > "Grey Alien" <> wrote in message
    > news:...
    >
    >>If I have the ff struct:
    >>
    >>struct A
    >>{
    >> unsigned int i;
    >> char s[LONG_ENOUGH];
    >>} a, b;
    >>
    >>
    >>And use them in code like this:
    >>
    >>a.i = 42 ;
    >>strcpy(a.s,"test");
    >>
    >>b.i = 100 ;
    >>
    >>b = a ;
    >>
    >>at this point, a (bitwise?) copy of a is made to b. Question is:
    >>
    >>1). is b.s now ptr to a.s ? (I think so)
    >>If so, what happens if for instance variable 'a' goes out of scope (?)
    >>
    >>2). Does the compiler generate an implicit "memcpy" or "memmove" behind
    >>the scenes when it sees an assignment like this (to avoid dangling ptrs)?
    >>

    >
    > The answer is 2. A structure assignment will cause a call to memcpy to be
    > made, or equivalent code emitted if the structure is small enough to make
    > this wasteful and the compiler is clever. [...]


    The compiler *may* do this, but it is not required
    to copy padding bytes and padding bits. Assignment only
    copies the value; padding bytes and bits are not part of
    the value of a struct, and might not be copied -- as they
    would be if memcpy() or an equivalent were used.

    --
     
    Eric Sosman, Jul 2, 2007
    #13
  14. Grey Alien

    Old Wolf Guest

    On Jul 3, 2:59 am, Eric Sosman <> wrote:
    > The compiler *may* do this, but it is not required
    > to copy padding bytes and padding bits. Assignment only
    > copies the value; padding bytes and bits are not part of
    > the value of a struct, and might not be copied -- as they
    > would be if memcpy() or an equivalent were used.


    Something that just occurred to me. Say we
    have:
    struct S
    {
    char s[10];
    };

    struct S s = { "hello" };
    struct S t;
    t = s;

    Initializing an automatic array from a string
    literal is only guaranteed to initialize the
    characters of the string and the null terminator
    - it could leave subsequent array entries (in
    this case, indices 6 through 9) uninitialized.

    So does the assignment 't = s' cause undefined
    behaviour by copying the values of uninitialized
    array members?
     
    Old Wolf, Jul 3, 2007
    #14
  15. On Jul 2, 8:02 pm, Old Wolf <> wrote:
    > On Jul 3, 2:59 am, Eric Sosman <> wrote:
    >
    > > The compiler *may* do this, but it is not required
    > > to copy padding bytes and padding bits. Assignment only
    > > copies the value; padding bytes and bits are not part of
    > > the value of a struct, and might not be copied -- as they
    > > would be if memcpy() or an equivalent were used.

    >
    > Something that just occurred to me. Say we
    > have:
    > struct S
    > {
    > char s[10];
    > };
    >
    > struct S s = { "hello" };
    > struct S t;
    > t = s;
    >
    > Initializing an automatic array from a string
    > literal is only guaranteed to initialize the
    > characters of the string and the null terminator
    > - it could leave subsequent array entries (in
    > this case, indices 6 through 9) uninitialized.


    Actually you are wrong about that, 9899:1999 §6.7.8p21:

    "If there are fewer initializers in a brace-enclosed list than there
    are elements or members
    of an aggregate, or fewer characters in a string literal used to
    initialize an array of known
    size than there are elements in the array, the remainder of the
    aggregate shall be
    initialized implicitly the same as objects that have static storage
    duration."

    Robert Gamble
     
    Robert Gamble, Jul 3, 2007
    #15
  16. Old Wolf <> writes:
    > On Jul 3, 2:59 am, Eric Sosman <> wrote:
    >> The compiler *may* do this, but it is not required
    >> to copy padding bytes and padding bits. Assignment only
    >> copies the value; padding bytes and bits are not part of
    >> the value of a struct, and might not be copied -- as they
    >> would be if memcpy() or an equivalent were used.

    >
    > Something that just occurred to me. Say we
    > have:
    > struct S
    > {
    > char s[10];
    > };
    >
    > struct S s = { "hello" };
    > struct S t;
    > t = s;
    >
    > Initializing an automatic array from a string
    > literal is only guaranteed to initialize the
    > characters of the string and the null terminator
    > - it could leave subsequent array entries (in
    > this case, indices 6 through 9) uninitialized.
    >
    > So does the assignment 't = s' cause undefined
    > behaviour by copying the values of uninitialized
    > array members?


    Not in n1124. n1124 6.2.6.1p6 says:

    The value of a structure or union object is never a trap
    representation, even though the value of a member of the structure
    or union object may be a trap representation.

    but that wording is not in the original C99 standard, or in C90; C99
    instead says:

    The values of padding bytes shall not affect whether the value of
    such an object is a trap representation. Those bits of a structure
    or union object that are in the same byte as a bit-field member,
    but are not part of that member, shall similarly not affect
    whether the value of such an object is a trap representation.

    I suspect that the intent all along was that your example would not
    invoke undefined behavior, but it had never been stated properly,
    which is why it needed to be corrected in n1124.

    By a strict reading of the original C99 or C90 standard, I think it
    could be argued that your example does invoke undefined behavior. I'd
    be interested in seeing an argument that it doesn't.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jul 3, 2007
    #16
  17. Robert Gamble <> writes:
    > On Jul 2, 8:02 pm, Old Wolf <> wrote:

    [...]
    >> Something that just occurred to me. Say we
    >> have:
    >> struct S
    >> {
    >> char s[10];
    >> };
    >>
    >> struct S s = { "hello" };
    >> struct S t;
    >> t = s;
    >>
    >> Initializing an automatic array from a string
    >> literal is only guaranteed to initialize the
    >> characters of the string and the null terminator
    >> - it could leave subsequent array entries (in
    >> this case, indices 6 through 9) uninitialized.

    >
    > Actually you are wrong about that, 9899:1999 §6.7.8p21:
    >
    > "If there are fewer initializers in a brace-enclosed list than there
    > are elements or members of an aggregate, or fewer characters in a
    > string literal used to initialize an array of known size than there
    > are elements in the array, the remainder of the aggregate shall be
    > initialized implicitly the same as objects that have static storage
    > duration."


    Argh, you're right. My comment about n1124 6.2.6.1p6 do not apply to
    the above example.

    They do, however, apply to the following:

    struct S
    {
    char s[10];
    };

    struct S s;
    struct S t;
    strcpy(s.s, "hello");
    t = s;

    (Assume that this appears inside a function definition, and that a
    "#include <string.h>" is visible.)

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jul 3, 2007
    #17
  18. Richard Heathfield <> wrote:
    > Flash Gordon said:
    > > Richard Heathfield wrote, On 30/06/07 20:56:
    > > > Serve Lau said:
    > > > > Its easy to see where the confusion comes from. There
    > > > > are situations where pointers degenerate into pointers,
    > > >
    > > > Pointers always degenerate into pointers.

    > >
    > > No they don't, they stay as pointers ;-)
    > >
    > > Knowing what Serve Lau must have intended I read it as
    > > "where arrays degenerate...".

    >
    > I know. Actually, arrays never actually do that. We often
    > say they do, but we're just being lazy. What we really
    > mean is that the name of an array, when used in an
    > expression, is often (indeed, *usually*) treated as if it
    > were a pointer to the array's first element.


    The effect is not limited to named arrays...

    int (*ap)[20] = malloc(sizeof *ap);
    int *ip = *ap;

    > The array itself never "degenerates" (or "decays", as it
    > is usually put) at all.


    There is change from an aggregate type to a non-aggregate type.
    We could say 'converted' as the standard does, but decay is
    more descriptive and notwithstanding. I don't see that as being
    'lazy'.

    --
    Peter
     
    Peter Nilsson, Jul 3, 2007
    #18
  19. Old Wolf said:

    <snip>
    >
    > Something that just occurred to me. Say we
    > have:
    > struct S
    > {
    > char s[10];
    > };
    >
    > struct S s = { "hello" };
    > struct S t;
    > t = s;
    >
    > Initializing an automatic array from a string
    > literal is only guaranteed to initialize the
    > characters of the string and the null terminator
    > - it could leave subsequent array entries (in
    > this case, indices 6 through 9) uninitialized.


    Not so. A part-initialisation is sufficient to invoke the static default
    initialiser rule.

    > So does the assignment 't = s' cause undefined
    > behaviour by copying the values of uninitialized
    > array members?


    No, because there aren't any.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Jul 3, 2007
    #19
  20. On Mon, 02 Jul 2007 19:38:12 -0700, Peter Nilsson <>
    wrote:

    >Richard Heathfield <> wrote:
    >> Flash Gordon said:
    >> > Richard Heathfield wrote, On 30/06/07 20:56:
    >> > > Serve Lau said:
    >> > > > Its easy to see where the confusion comes from. There
    >> > > > are situations where pointers degenerate into pointers,
    >> > >
    >> > > Pointers always degenerate into pointers.
    >> >
    >> > No they don't, they stay as pointers ;-)
    >> >
    >> > Knowing what Serve Lau must have intended I read it as
    >> > "where arrays degenerate...".

    >>
    >> I know. Actually, arrays never actually do that. We often
    >> say they do, but we're just being lazy. What we really
    >> mean is that the name of an array, when used in an
    >> expression, is often (indeed, *usually*) treated as if it
    >> were a pointer to the array's first element.

    >
    >The effect is not limited to named arrays...
    >
    > int (*ap)[20] = malloc(sizeof *ap);
    > int *ip = *ap;
    >
    >> The array itself never "degenerates" (or "decays", as it
    >> is usually put) at all.

    >
    >There is change from an aggregate type to a non-aggregate type.
    >We could say 'converted' as the standard does, but decay is
    >more descriptive and notwithstanding. I don't see that as being
    >'lazy'.


    Why generate new words to describe what the standard explains very
    clearly. With three exception, an expression of array type
    **evaluates** to the address of the first element with type pointer to
    element type. No decay, no degeneration, no change from aggregate to
    non-aggregate, no conversion. Just an evaluation.


    Remove del for email
     
    Barry Schwarz, Jul 3, 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. Chris Fogelklou
    Replies:
    36
    Views:
    1,391
    Chris Fogelklou
    Apr 20, 2004
  2. nagy
    Replies:
    36
    Views:
    1,011
    Terry Reedy
    Jul 20, 2006
  3. Eric Laberge

    Array assignment via struct

    Eric Laberge, Aug 4, 2005, in forum: C Programming
    Replies:
    36
    Views:
    920
    Dave Thompson
    Aug 14, 2005
  4. Chris
    Replies:
    34
    Views:
    1,526
  5. Noob
    Replies:
    25
    Views:
    1,478
    Nick Keighley
    Dec 9, 2009
Loading...

Share This Page