Thread: (struct) a= (struct) b ; ANSI C ?

  1. #1
    Alessio Stella
    Join Date
    May 2008
    Location
    Italy, Bologna
    Posts
    251

    (struct) a= (struct) b ; ANSI C ?

    I have been told and I realized myself that in many C situations if i have two structs of the same kind I can assing one another and what will happen will be a corresponding assignment member by member ( field by field)

    But the question is :
    (1) Is it quite general?
    (2) Is it ANSI C ?

    Thank you

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You have two VARIABLES of the same struct, you can assign them.

    If there are two structures with the same content, they are, in the view of the compiler, different types, and can't be assigned directly. Why would you want that? You either use the same struct, or don't.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by mynickmynick View Post
    I have been told and I realized myself that in many C situations if i have two structs of the same kind I can assing one another and what will happen will be a corresponding assignment member by member ( field by field)

    But the question is :
    (1) Is it quite general?
    (2) Is it ANSI C ?

    Thank you
    Yep, you can assign variables that are of the same struct type as it's syntactically analogous to assignment between any basic type like char, int, or float.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    But watch out for structs containing pointers.

    You end up with "shallow" aliases of the pointers, not "deep" copies of the what the pointers point to.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303
    Quote Originally Posted by Salem View Post
    But watch out for structs containing pointers.

    You end up with "shallow" aliases of the pointers, not "deep" copies of the what the pointers point to.
    What is a "shallow" alias of a pointer? And why would you want a deep copy of what they point to? As long as it's a pointer of the same type then it's exactly the same as the other pointer in terms of its value and what it points to, is it not?

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    struct foo {
       char *shallow;
    };
    
    struct foo a, b;
    
    a.shallow = malloc(10);
    b = a;
    free( a.shallow );
    // now b is up the creek without a paddle, pointing to deallocated memory
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    But Salem, sir, a.shallow is also pointing at deallocated memory. Whoopteedoo.

    I thought with your warning of "shallow alias" you might be alluding to some compiler optimization issue.

    As for the original problem: (struct) a= (struct) b...

    I use such casting when I know there is a fixed array size. So a typedef of a struct of said size, casting both sides, and assignment is the trick to get the compiler to issue inline machine-level block moves without calling a memcpy() function.

    Darn, there goes one of my patented uber-cool techniques.
    Last edited by nonoob; 05-06-2009 at 06:56 AM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by nonoob
    a.shallow is also pointing at deallocated memory
    But it is easy to see that a.shallow points to deallocated memory, and in fact one can just turn it into a null pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by nonoob View Post
    I use such casting when I know there is a fixed array size. So a typedef of a struct of said size, casting both sides, and assignment is the trick to get the compiler to issue inline machine-level block moves without calling a memcpy() function.

    Darn, there goes one of my patented uber-cool techniques.
    memcpy() is often better [faster/more optimized] than the corresponding inlined struct copy code, unless the compiler inlines the memcpy in the first place, in which case all you have gained is a bit of obfucation.

    If the data is really short, the compiler SHOULD be able to inline the memcpy itself.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    .
    Join Date
    Nov 2003
    Posts
    307
    deep copies refer to allocating memory and copying the contents of allocated objects into the destination pointer's allocated memory.
    i.e.,
    b.shallow needs it own separate chunk of allocated memory, with a copy of whatever was in a.shallow placed in that memory.

  11. #11
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I doubt the compiler inlines the memcpy()... After all, it may or may not be standard C-library... so it may not resolve to something normal.

    memcpy() or any function call needs at least stack push(s) and cleanup. Plus the call itself. The fact that the number-of-bytes to move is a variable is probably the same number of clocks these days as assigning a constant.

    How can a memcpy() be any more optimized internally than an inline move of a fixed number of bytes?

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    1. The compiler CERTAINLY _WILL_ inline memcpy() - at least gcc and MS compilers do that. Sure, it can't ALWAYS do it - and the relevant header files will need to be included, sufficient optimization enabled, etc. But the compiler can, if it likes to, inline memcpy. Try it for yourself, and check the compiler generated code at various optimization levels and with/without the <string.h> header. memcpy() is commonly in the category of "intrinsic" functions - functions that the compiler itself KNOWS how they are implemented.

    2. An optimized memcpy can do moves in bigger chunks than one or four bytes at a time (e.g. using SSE instructions and/or unrolling the loop), which is most likely what the inline version uses [at least on a 32-bit machine]. Using prefetch/block copying techniques are definitely faster than the trivial form produced by compilers [in my experience].

    Obviously, _IF_ the compiler generates a proper call to memcpy then you are probably going to end up with a bit of overhead compared to the inline version.

    However, the inline version in x86 probably uses the REP MOVS instruction, which requires certain registers to be used. Unless your function is really trivial, those registers are probably being used for somehting else, so even tho you are not making a call to another function, there are still push & pop instructions involved in getting the right data into the right registers and preserving the original content of those registers.

    Obviously, which is better, inline or call to memcpy will depend on the size of the copy - for small copies, inline is probably faster. For larger blocks, I'm certain that the overhead of a call is better than the inline version.

    The other question is of course why the fixed array isn't (part of) a struct in the first place - if that's how you are using it...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  2. Function validation.
    By Fhl in forum C Programming
    Replies: 10
    Last Post: 02-22-2006, 08:18 AM
  3. Search Engine - Binary Search Tree
    By Gecko2099 in forum C Programming
    Replies: 9
    Last Post: 04-17-2005, 02:56 PM
  4. problem with structures and linked list
    By Gkitty in forum C Programming
    Replies: 6
    Last Post: 12-12-2002, 06:40 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM