ZKK
ZKK

Reputation: 124

C: are operations between members allowed in the struct declaration?

I am trying to use a struct to represent an object with three properties, but the third property is dependent on the first two. So, I basically attempted this:

typedef struct{
    int x;
    int y;
    int z = x + y;
}xyz_type;

But I get a compiler error. Does the C language not support this sort of behavior or am I missing the correct syntax for something like this? If it is not supported what would be a better way to achieve something like this?

Expected behavior: z will be initialized with the sum of the initialization values of the other two and then stay independent

Upvotes: 0

Views: 228

Answers (1)

Clifford
Clifford

Reputation: 93546

The struct defines a type, not an instance. You cannot define initialisation for a type. For that you would need a constructor like that provided by C++, but not C.

However, you can refer to in instance of the structure within the structure's own initialiser:

typedef struct
{
    int x;
    int y;
    int z;
} xyz_type ;

xyz_type instance = 
         { 10,                         // x = 10
           5,                          // y = 5
           instance.x + instance.y } ; // z = 15


instance.x = 0 ; // x = 0, z is unchanged

You can be explicit about which members are being assigned in an initialiser:

xyz_type instance = { .x=10, 
                      .y=5,
                      .z=instance.x+instance.y} ;

which is useful in more complex structures with other members, however the ordering remains critical - members are assigned in the order they are defined in the struct definition, not the order they appear in the initialiser, so z in this case must be defined after both x and y.

This is not equivalent to a constructor, because it must be coded explicitly at each instantiation. It is possible to automate the initialisation to some extent by writing a macro. For example:

#define XYZ_INIT( xinit, yinit ) {.x=(xinit),\
                                  .y=(yinit),\
                                  .z=(xinit)+(yinit)}

then;

xyz_type instance = XYZ_INIT( 10, 5 ) ;

Since macros can be problematic, and are not type-safe, you might prefer an initialiser function as below:

xyz_type create_xyz(int x, int y) 
{ 
    return (xyz_type){ .x = x, .y = y, .z = x + y }; 
}

then:

xyz_type instance = create_xyz( 10, 5 ) ;

Upvotes: 3

Related Questions