Thread: Cycling through structure

  1. #1
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55

    Cycling through structure

    Suppose S is a structure:
    Code:
    typedef struct {
    
       type s1;
       type s2;
    // ...
       type sn;
    } S;
    
    S myS;
    Is there a way to assign values to myS without referring to s1, s2, ..., sn explicitly, i.e., instead of
    Code:
    myS.s1 = v1;
    myS.s2 = v2;
    //...
    myS.sn = vn;
    is something like
    Code:
    for (int i=1; i<=n; i++) {
           /* Do something like myS.i = vi */
    }
    possible? Thanks!

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Use an array or a container like std::vector instead of n separate member variables.
    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

  3. #3
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    So is it correct to say that there is no way to enumerate over member variables in a struct, likewise in a class? The only way I could think of would be to access via pointers, but you would have to know the size of individual members. Are you guaranteed a correct layout from a C/C++ compiler in order for this to work?

    edit: By "correct layout" I mean are you guaranteed the order of members to be the same as defined?
    Last edited by neandrake; 04-10-2009 at 03:00 PM.
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

  4. #4
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    Followup:

    It looks like you are guaranteed the order of members defined in a struct, however the compiler may need to pad fields, depending on architecture. There is probably no good way to do this.

    Byte Alignment and Ordering in Message Definition
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

  5. #5
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by neandrake View Post
    Followup:

    It looks like you are guaranteed the order of members defined in a struct, however the compiler may need to pad fields, depending on architecture. There is probably no good way to do this.

    Byte Alignment and Ordering in Message Definition
    True, although 99.9% of the programmers ignore this fact completely. How often haven't I seen fread(&file_header, 1, sizeof(file_header), some_file_type_handle);

    So it's generally ignored completely.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by EVOEx View Post
    True, although 99.9% of the programmers ignore this fact completely. How often haven't I seen fread(&file_header, 1, sizeof(file_header), some_file_type_handle);

    So it's generally ignored completely.
    But for portable code, you can almost guarantee that the header is carefully constructed in such a way that it is unlikely to have any (unknown) gaps in it - either by asking the compiler to not add gaps, or by arranging the content in such a way that in almost all compilers the data is aligned properly no matter what compiler/processor architecture it is.

    Or the code is written such that it reads each element at a time.

    Also, as long as all elements in a struct are the same type (or a set of members are the same type and consecutive elements), you could use a pointer to that type - it should increment the same way as a pointer as the compiler arranges the elements. But if you have more than three of something, it's likely that you actually WANT an array anyways.

    --
    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.

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    What are you trying to accomplish with this?

  8. #8
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by slippy View Post
    is something like
    Code:
    for (int i=1; i<=n; i++) {
           /* Do something like myS.i = vi */
    }
    possible? Thanks!
    It's technically possible given the struct in the OP, and ones like it.
    Code:
    #include <iostream>
    #include <cstdio>
    #include <boost/preprocessor/arithmetic/add.hpp>
    #include <boost/preprocessor/cat.hpp>
    #include <boost/preprocessor/repetition/repeat_from_to.hpp>
    #include <boost/preprocessor/list/at.hpp>
    
    typedef struct {
    
       int s1;
       int s2;
    // ...
       int s3;
    } S;
    
    // constructs "<struct>.<fieldname><number> = <value>;"
    #define INIT_EACH_MEMBER_STATIC_INT(NextDim, Number, Data) \
        BOOST_PP_LIST_AT(Data, 0).BOOST_PP_CAT(BOOST_PP_LIST_AT(Data, 1), Number) = BOOST_PP_LIST_AT(Data, 2);
    
    // loops from startElem to startElem+elements constructing the assignment for each with the above macro
    #define INIT_EACH_MEMBER_STATIC(structure, namePrefix, startElem, elements, value) \
        BOOST_PP_REPEAT_FROM_TO(startElem, BOOST_PP_ADD(startElem, elements), INIT_EACH_MEMBER_STATIC_INT, (structure, (namePrefix, (value, BOOST_PP_LIST_NIL))))
    
    // like the first macro, constructs
    // <struct>.<fieldname><number> = <varprefix><value>;
    #define INIT_EACH_MEMBER_VARIABLE_INT(NextDim, Number, Data) \
        BOOST_PP_LIST_AT(Data, 0).BOOST_PP_CAT(BOOST_PP_LIST_AT(Data, 1), Number) = BOOST_PP_CAT(BOOST_PP_LIST_AT(Data, 2), Number);
    
    #define INIT_EACH_MEMBER_VARIABLE(structure, namePrefix, startElem, elements, varPrefix) \
        BOOST_PP_REPEAT_FROM_TO(startElem, BOOST_PP_ADD(startElem, elements), INIT_EACH_MEMBER_VARIABLE_INT, (structure, (namePrefix, (varPrefix, BOOST_PP_LIST_NIL))))
    
    int main()
    {
        S myStructVar;
        // make every member equal 56
        INIT_EACH_MEMBER_STATIC(myStructVar, s, 1, 3, 56);
        printf("S members: s1 = %d, s2 = %d, s3 = %d\n", myStructVar.s1, myStructVar.s2, myStructVar.s3);
        // you could also use a macro for this to auto generate init variables 
        // and input for N values
        int initS1, initS2, initS3;
        std::cout << "Enter three ints: ";
        std::cin >> initS1 >> initS2 >> initS3;
        // make each member equal its eqivalent initS 
        INIT_EACH_MEMBER_VARIABLE(myStructVar, s, 1, 3, initS);
        printf("S members: s1 = %d, s2 = %d, s3 = %d\n", myStructVar.s1, myStructVar.s2, myStructVar.s3);
    }
    So it can be done, but it is has a limited applicability given the stringent requirements on naming / initialization etc and the amount of manual bookkeeping you have to contend with. Use an array or vector for a much easier life.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by neandrake View Post
    It looks like you are guaranteed the order of members defined in a struct,
    In C++, that's only true for PoD struct types. For non-PoD types (which includes, among other things, structs with a declared destructor or a virtual function) the order is not guaranteed.

    Add to that the padding in structs, and the implementation defined layout of basic types (int, double, enums, pointers, etc) and it is usually better to write code that does not rely on specific layout of types in memory, if you care at all about portability.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    The only thing I could see where you would want to guarantee the layout would be in microchips -- in which you should know the architecture very well. Even then you would probably doing a lot of stuff in assembly if it really mattered.
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem referencing structure elements by pointer
    By trillianjedi in forum C Programming
    Replies: 19
    Last Post: 06-13-2008, 05:46 PM
  2. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  3. Cycling through the fields in a structure
    By clancyPC in forum C Programming
    Replies: 3
    Last Post: 03-23-2005, 12:27 PM
  4. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM
  5. C structure within structure problem, need help
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 11-30-2001, 05:48 PM