Re: Copying Aggregate Data Types in C

Discussion in 'C Programming' started by Nate Eldredge, Dec 17, 2008.

  1. "Jujitsu Lizard" <> writes:

    > In the general case, if s1 and s2 are structures, am I allowed to just use:
    >
    > s1 = s2;
    >
    > ?


    Yes.

    (In the days of K&R I, you weren't allowed to assign structures to each
    other; you'd have to use memcpy. Nor could you pass and return them by
    value to and from functions; you had to use pointers. But even K&R I
    says "these restrictions will be removed in future versions", and ANSI C
    did so.)

    > I'm assuming the compiler will puke if that isn't legal.
    >
    > And is that better or worse than:
    >
    > memcpy(&s1, &s2, sizeof(s1));
    >
    > ?


    A good compiler should optimize them into the same code.

    > Any guaranteed behavior by the compiler there?


    The only thing guaranteed is that both options have the effect of
    copying one object to the other. The C standard of course doesn't
    specify how they should be implemented, nor which one should be more
    efficient. But in a good compiler, they should be equivalent in
    performance as well as effect.

    > For small structs I'm going to guess the compiler would just copy them
    > a word at a time. But for larger structs, I'd guess the compiler is
    > going to perhaps do a memcpy() anyway.


    Right, that's what reasonable compilers do in my experience.
     
    Nate Eldredge, Dec 17, 2008
    #1
    1. Advertising

  2. Nate Eldredge

    jameskuyper Guest

    Nate Eldredge wrote:
    > "Jujitsu Lizard" <> writes:
    >
    > > In the general case, if s1 and s2 are structures, am I allowed to just use:
    > >
    > > s1 = s2;
    > >
    > > ?

    ....
    > > And is that better or worse than:
    > >
    > > memcpy(&s1, &s2, sizeof(s1));
    > >
    > > ?

    >
    > A good compiler should optimize them into the same code.


    The memcpy() is required to copy the specified number of bytes,
    starting at the beginning of s2; that includes the padding bytes. When
    a given type has multiple representations for the same value (as can
    be the case for any type other than unsigned types with no padding
    bits), the simple assignment is not required to write the same
    representation of that value that was read from s1. Also, the simple
    assignment is not required to copy the padding bytes. Since it has
    fewer restrictions, there's more room for optimization of the simple
    assignment.

    However, in practice, the only such optimization that seems plausible
    would apply if there are padding bytes at the end of the struct. The
    simple assignment could be optimized to not bother copying those
    bytes. However, that's a pretty minor optimization. In practice, many
    memcpy() implementations copy using multi-byte instructions, if the
    alignment of the source and the destination makes use of the such
    instructions possible. As a result, I'd expect that any padding added
    to a struct type for alignment purposes might actually turn such an
    "optimization" into a pessimization, or at least cause it to have no
    effect.
     
    jameskuyper, Dec 17, 2008
    #2
    1. Advertising

  3. On Wed, 17 Dec 2008 10:23:04 -0800, Nate Eldredge <> wrote:
    >> memcpy(&s1, &s2, sizeof(s1));
    >>
    >> ?

    >
    >A good compiler should optimize them into the same code.


    memmove, I should think, rather than memcpy.


    --
    #include <standard.disclaimer>
    _
    Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
     
    Kevin D. Quitt, Dec 17, 2008
    #3
  4. Kevin D. Quitt <> writes:
    > On Wed, 17 Dec 2008 10:23:04 -0800, Nate Eldredge <> wrote:
    >>> memcpy(&s1, &s2, sizeof(s1));
    >>>
    >>> ?

    >>
    >>A good compiler should optimize them into the same code.

    >
    > memmove, I should think, rather than memcpy.


    Why? If s1 and s2 are distinct declared objects, there's no chance of
    overlap.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 17, 2008
    #4
  5. Nate Eldredge

    jameskuyper Guest

    Kevin D. Quitt wrote:
    > On Wed, 17 Dec 2008 10:23:04 -0800, Nate Eldredge <> wrote:
    > >> memcpy(&s1, &s2, sizeof(s1));
    > >>
    > >> ?

    > >
    > >A good compiler should optimize them into the same code.

    >
    > memmove, I should think, rather than memcpy.


    In order for the extra protections provided by memmove() to matter,
    the two structures would have to be stored in distinct but overlapping
    blocks of memory. Offhand, I can't think of any way for that to be
    achieved without undefined behavior - do you know of any? Without that
    issue to worry about, memcpy() should never be slower than memmove(),
    and should at least occasionally be faster.
     
    jameskuyper, Dec 17, 2008
    #5
  6. Nate Eldredge

    James Kuyper Guest

    Jujitsu Lizard wrote:
    > "jameskuyper" <> wrote in message
    > news:...
    >> Kevin D. Quitt wrote:
    >>> On Wed, 17 Dec 2008 10:23:04 -0800, Nate Eldredge <>
    >>> wrote:
    >>> >> memcpy(&s1, &s2, sizeof(s1));
    >>> >>
    >>> >> ?
    >>> >
    >>> >A good compiler should optimize them into the same code.
    >>>
    >>> memmove, I should think, rather than memcpy.

    >>
    >> In order for the extra protections provided by memmove() to matter,
    >> the two structures would have to be stored in distinct but overlapping
    >> blocks of memory. Offhand, I can't think of any way for that to be
    >> achieved without undefined behavior - do you know of any? Without that
    >> issue to worry about, memcpy() should never be slower than memmove(),
    >> and should at least occasionally be faster.

    >
    > Are you saying that memmove() is cool with memmove(a, a, n)?


    I didn't actually say that - I referred only to "distinct" blocks of
    memory, and 'a' is very definitely not distinct from 'a'. However, what
    you say does happen to be true, so long as n <= sizeof a. It's pretty
    pointless, but why should it be a problem? It would be a problem with
    memcpy(); but the whole point of memmove is that it has defined behavior
    even when the source and destination overlap. That's just an extreme
    case of overlap.
     
    James Kuyper, Dec 18, 2008
    #6
  7. In article <>,
    Jujitsu Lizard <> wrote:

    >"jameskuyper" <> wrote in message
    >news:...


    >> In order for the extra protections provided by memmove() to matter,
    >> the two structures would have to be stored in distinct but overlapping
    >> blocks of memory. Offhand, I can't think of any way for that to be
    >> achieved without undefined behavior - do you know of any? Without that
    >> issue to worry about, memcpy() should never be slower than memmove(),
    >> and should at least occasionally be faster.


    >Are you saying that memmove() is cool with memmove(a, a, n)?


    This question would make more sense if it referred to memcpy()
    instead of memmove().

    James, why do you think that memmove() only matters for *distinct*
    blocks of memory? Isn't it incorrect to translate "a = a" to
    memcpy(&a, &a, sizeof(a)) but correct to translate it to
    memmove(&a, &a, sizeof(a))?

    (Obviously the compiler can see that a and a are the same, but
    it might be, say, a and a[j] where i and j are sometimes equal.)

    -- Richard
    --
    Please remember to mention me / in tapes you leave behind.
     
    Richard Tobin, Dec 18, 2008
    #7
  8. Nate Eldredge

    James Kuyper Guest

    Richard Tobin wrote:
    > In article <>,
    > Jujitsu Lizard <> wrote:
    >
    >> "jameskuyper" <> wrote in message
    >> news:...

    >
    >>> In order for the extra protections provided by memmove() to matter,
    >>> the two structures would have to be stored in distinct but overlapping
    >>> blocks of memory. Offhand, I can't think of any way for that to be
    >>> achieved without undefined behavior - do you know of any? Without that
    >>> issue to worry about, memcpy() should never be slower than memmove(),
    >>> and should at least occasionally be faster.

    >
    >> Are you saying that memmove() is cool with memmove(a, a, n)?

    >
    > This question would make more sense if it referred to memcpy()
    > instead of memmove().
    >
    > James, why do you think that memmove() only matters for *distinct*
    > blocks of memory?


    Because there's no point in using either method, if the blocks of memory
    are known to be the same. If the compiler can't be sure, then unless the
    objects are volatile, it's probably best to translate the code into the
    equivalent of

    if(&s1 == &s2)
    memcpy(&s1, &s2, sizeof s1);

    > ... Isn't it incorrect to translate "a = a" to
    > memcpy(&a, &a, sizeof(a)) but correct to translate it to
    > memmove(&a, &a, sizeof(a))?


    True, but you mentioned memmove() in response to a question about
    s1 = s2;

    > (Obviously the compiler can see that a and a are the same, but
    > it might be, say, a and a[j] where i and j are sometimes equal.)


    Unless 'a' is volatile, I'd expect the compiler to treat a=a; as a nop.
    I will grant you that if a is a volatile object of struct type, then the
    compiler should generate code for a=a equivalent to memmove(&a, &a,
    sizeof a).
     
    James Kuyper, Dec 18, 2008
    #8
  9. James Kuyper <> writes:
    > Richard Tobin wrote:

    [...]
    >> (Obviously the compiler can see that a and a are the same, but
    >> it might be, say, a and a[j] where i and j are sometimes equal.)

    >
    > Unless 'a' is volatile, I'd expect the compiler to treat a=a; as a
    > nop. I will grant you that if a is a volatile object of struct type,
    > then the compiler should generate code for a=a equivalent to
    > memmove(&a, &a, sizeof a).


    And for a given implementation, memcpy(&a, &a, sizeof a) might be
    equivalent to memmove(&a, &a, sizeof a). The language doesn't
    guarantee that memcpy works when its first two arguments are the same,
    but an implementation might, and a compiler is free to take advantage
    of that.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Dec 18, 2008
    #9
  10. My original point is that there's no reason to use memcpy. Assuming the
    implementation of the two are actually distinct, one at best gains a few
    cycles. I suppose if you're calling it trillions of times, that might
    actually make a difference, but...

    memmove is always safe, memcpy isn't.


    --
    #include <standard.disclaimer>
    _
    Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
     
    Kevin D. Quitt, Dec 18, 2008
    #10
  11. Nate Eldredge

    Guest

    On Dec 18, 9:23 pm, Kevin D. Quitt <> wrote:
    > My original point is that there's no reason to use memcpy. Assuming the
    > implementation of the two are actually distinct, one at best gains a few
    > cycles. I suppose if you're calling it trillions of times, that might
    > actually make a difference, but...
    >
    > memmove is always safe, memcpy isn't.


    Use memcpy when there's no benifit of using memmove. Or always use
    memmove and use some extra cycles, at the benifit of being allowed to
    be lazy about whether the area pointed to by the two pointers overlaps
    or not.
     
    , Dec 18, 2008
    #11
  12. Nate Eldredge

    CBFalconer Guest

    Jujitsu Lizard wrote:
    >

    .... snip ...
    >
    > Are you saying that memmove() is cool with memmove(a, a, n)?


    The simplest thing is to read the C standard on the subject:

    7.21.2.2 The memmove function

    Synopsis
    [#1]
    #include <string.h>
    void *memmove(void *s1, const void *s2, size_t n);

    Description

    [#2] The memmove function copies n characters from the
    object pointed to by s2 into the object pointed to by s1.
    Copying takes place as if the n characters from the object
    pointed to by s2 are first copied into a temporary array of
    n characters that does not overlap the objects pointed to by
    s1 and s2, and then the n characters from the temporary
    array are copied into the object pointed to by s1.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
     
    CBFalconer, Dec 18, 2008
    #12
  13. On Wed, 17 Dec 2008 22:56:10 -0500, "Jujitsu Lizard"
    <> wrote:

    >"jameskuyper" <> wrote in message
    >news:...
    >> Kevin D. Quitt wrote:
    >>> On Wed, 17 Dec 2008 10:23:04 -0800, Nate Eldredge <>
    >>> wrote:
    >>> >> memcpy(&s1, &s2, sizeof(s1));
    >>> >>
    >>> >> ?
    >>> >
    >>> >A good compiler should optimize them into the same code.
    >>>
    >>> memmove, I should think, rather than memcpy.

    >>
    >> In order for the extra protections provided by memmove() to matter,
    >> the two structures would have to be stored in distinct but overlapping
    >> blocks of memory. Offhand, I can't think of any way for that to be
    >> achieved without undefined behavior - do you know of any? Without that
    >> issue to worry about, memcpy() should never be slower than memmove(),
    >> and should at least occasionally be faster.

    >
    >Are you saying that memmove() is cool with memmove(a, a, n)?


    Yes. memmove allows overlapping source and destination. It is
    required to behave as if the data were first copied to a temporary
    buffer and then copied to the destination.

    --
    Remove del for email
     
    Barry Schwarz, Dec 19, 2008
    #13
    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. Guiding5
    Replies:
    1
    Views:
    1,714
    Dimitre Novatchev
    Feb 28, 2006
  2. ramu
    Replies:
    2
    Views:
    328
    rlblaster
    Feb 20, 2006
  3. CBFalconer

    Re: Copying Aggregate Data Types in C

    CBFalconer, Dec 17, 2008, in forum: C Programming
    Replies:
    46
    Views:
    1,026
    CBFalconer
    Dec 25, 2008
  4. Gary Roach
    Replies:
    0
    Views:
    114
    Gary Roach
    Sep 1, 2013
  5. Fábio Santos
    Replies:
    0
    Views:
    122
    Fábio Santos
    Sep 4, 2013
Loading...

Share This Page