herr_mueller12
herr_mueller12

Reputation: 21

C access enum from struct

My problem is that car_name_str could not be resolved. Why is it not callable and I want to keep the code structure?

I want to keep the structure as struct with union and enum (different datatypes).

Template: How can mixed data types (int, float, char, etc) be stored in an array?

//car_union.h
    typedef struct {
        enum { number_of_seats_int, car_cost_float, car_name_str } type;    
        union {
            int number_of_seats;
            float car_cost;
            char* car_name;
            } value;
    }Car_data_ex[30][3];   

    extern Car_data_ex *Car_data[30][3];

//fill_car.c
#include "car_union.h"
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str;  //-> because pointer but doesnt work
Car_data[0][0]->value->car_name= "land rover";

Car_data[0][1]->type = car_cost_float;    //doesnt work
Car_data[0][1]->value->car_cost= 45000;

Upvotes: 0

Views: 238

Answers (3)

Serge Ballesta
Serge Ballesta

Reputation: 149145

You have over complexified everything.

A typedef is just to give an alias to a (complex) type. Here the type is a struct containing an enum and an union. So it should be:

typedef struct {
    enum { number_of_seats_int, car_cost_float, car_name_str } type;
    union {
        int number_of_seats;
        float car_cost;
        char* car_name;
        } value;
}Car_data_ex;

Next, using an array of pointers can make sense, but provided each pointer in the array does point to a true object. Here you only want a plain (2D) array:

Car_data_ex Car_data[30][3];

Once this has been done, you can write with no error or warning:

Car_data[0][0].type = car_name_str;
Car_data[0][0].value.car_name= "land rover";

Car_data[0][1].type = car_cost_float;
Car_data[0][1].value.car_cost= 45000;

And you should avoid extern Car_data_ex Car_data[30][3];. It declares a global array, that will have to be defined in one single compilation unit (.c file). Here again, it can make sense, but IMHO it is a rather advanced feature that can be hard to correctly use. And nothing in the shown code lets think that is is required...

Upvotes: 2

Petr Skocik
Petr Skocik

Reputation: 60127

Regardless of what's in your struct, when you do

typedef struct Car_dataStructTag{
    //...
}Car_data_ex[30][3];

(I've tagged the struct so it can be referred to by struct Car_dataStructTag), then Car_data_ex is a type alias resolving to struct Car_dataStructTag [30][3] which means

extern Car_data_ex *Car_data[30][3];

is fully equivalent to

extern struct Car_dataStructTag (*Car_data[30][3])[30][3];

which means Car_data[x][y] is a pointer to a two-dimensional array of struct Car_dataStructTag, which is definitely not something you can apply -> to.

Try:

typedef struct Car_dataStructTag{
    //...
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];

in a compiler -- it gets accepted, confirming the declaration equivalence.

Running into situations such as this one is why it's generally considered ill-advisable to typedef arrays or pointers.

Upvotes: 2

Ackdari
Ackdari

Reputation: 3498

Just remove the [30][3] from the type def, like this

#include <stdio.h>

//car_union.h
typedef struct {
    enum { number_of_seats_int, car_cost_float, car_name_str } type;    
    union {
        int number_of_seats;
        float car_cost;
        char* car_name;
    } value;
}Car_data_ex;   

extern Car_data_ex *Car_data[30][3];

int main() {
    Car_data_ex *Car_data[30][3];
    Car_data[0][0]->type = car_name_str;  //-> because pointer but doesnt work
    Car_data[0][0]->value.car_name= "land rover";

    Car_data[0][1]->type = car_cost_float;    //doesnt work
    Car_data[0][1]->value.car_cost= 45000;
}

Upvotes: 3

Related Questions