Iterating over same type struct members in C

12,521

Solution 1

The easiest way would be to create a union, one part which contains each member individually and one part which contains an array. I'm not sure if platform-dependent padding might interfere with the alignment.

Solution 2

Most of the attempts using a union with an array are prone to failure. They stand a decent chance of working as long as you only use int's, but for other, especially smaller, types, they're likely to fail fairly frequently because the compiler can (and especially with smaller types often will) add padding between members of a struct, but is not allowed to do so with elements of an array).

C does, however, have an offsetof() macro that you can use. It yields the offset of an item in a struct, so you can create an array of offsets, then (with a bit of care in casting) you can add that offset to the address of the struct to get the address of the member. The care in casting is because the offset is in bytes, so you need to cast the address of the struct to char *, then add the offset, then cast the result to the type of the member (int in your case).

Solution 3

From the language point of view: you can't. data members of the struct are not... er.. "iteratible" in C, regardless of whether they are of the same type or of different types.

Use an array instead of a bunch of independent members.

Solution 4

You can also use an unnamed union/struct:

struct foo {
    union {
        struct {
            int mem1;
            int mem2;
            int mem3;
            int mem4;
        };
        int elements[4];
    };
};

foo thefoo;
for (int i = 0; i < 4; ++i) {
    thefoo.elements[i] = i;
}

This might not work on some compilers, int this case you'll have to explicitily name the union and struct inside foo,

Solution 5

Here's another approach; I've never had reason to do this, but it has the advantage of not mucking up the struct definition. Create a an array of pointers to the members you're interested in, and then iterate over that array:

typedef struct { int mem1; int mem2; int mem3, int mem4; } foo;
...
foo theStruct;
int *structMembers[4] = { &theStruct.mem1, &theStruct.mem2, 
                          &theStruct.mem3, &theStruct.mem4};
...
for (i = 0; i < 4; i++)
{
  printf("%d\n", *structMembers[i]);
}

This way you don't have to worry about alignment issues biting you, and you can arbitrarily order how you want to iterate over the members (e.g., you could order it so the walk is "mem4, mem3, mem2, mem1").

Share:
12,521
Misha M
Author by

Misha M

Updated on June 19, 2022

Comments

  • Misha M
    Misha M almost 2 years

    Is it possible to iterate of a C struct, where all members are of same type, using a pointer. Here's some sample code that does not compile:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct
    {
        int mem1 ;
        int mem2 ;
        int mem3 ;
        int mem4 ;
    } foo ;
    
    void my_func( foo* data )
    {
        int i ;
        int* tmp = data ; // This line is the problem
    
        for( i = 0; i < 4; ++i )
        {
            ++tmp ;
            printf( "%d\n", *tmp ) ;
        }
    }
    
    int main()
    {
        foo my_foo ;
        //
        my_foo.mem1 = 0 ;
        my_foo.mem2 = 1 ;
        my_foo.mem3 = 2 ;
        my_foo.mem4 = 3 ;
        //
        my_func( &my_foo ) ;
        return 0 ;
    }
    

    The members of foo should be aligned in memory to be one after another, assuming your compiler/kernel does not try to provide stack protection for buffer overflow.

    So my question is:

    How would I iterate over members of a C struct that are of the same type.