struct vs enum for constants

Status
Not open for further replies.

linuxgeek

Well-known member
I'm trying to handle the config for multiple sensors, so I thought about putting things in a struct. So that I can easily add a new config for another sensor. "enum" seems to be the favored way (altho not sure why). I mostly want to minimize the memory footprint so it's not obvious to me how "enum" stores the constants.

For example this is how I would do the struct:
Code:
struct bmxConfig  {
  uint8_t dig_H1, dig_H3, digH6;
  uint16_t dig_T1, dig_P1, dig_H4, dig_H5;
  int16_t  dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9, dig_H2;  
};

Would an enum be better for this? Would it take up more memory?

Thanks.
 
enum creates compile-time values, very roughly like a #define. A struct also creates a compile-time definition, but this definition can be instantiated (which is where you start to use memory).
If I where coding this struct I'd place each element on a separate line, with comments.
Remember the Rule of Twos: Two years from now [when Ops calls you at 2 o'clock in the morning], you don't want to need two hours to figure out your own code.
 
You can define enum datatype with ': datatype'.
Code:
enum something : uint8_t 
{
these, are, now, eightbit
};
Do be aware though that the actual size of a struct may be slightly more than the sum of it's members because it pads data so it all fits nicely, maybe a few bytes more. Lookup "__attribute__((__packed__))" for more info. Probably not that tight on space though.
 
That helps. It looks like structs are the way to go for this, since the values can't be known at compile-time. I have to get these values from each sensor at run-time.

But is it possible to have different datatypes in the same enum?

The example above is for uint8_t, but can I also have int16_t variables in the same enum?
If it's necessary to create separate enums for each datatype that probably negates the advantage of using them in that scenario.
 
For me, it would help to see more of usage. That is I use enums when I am trying to define a set of valid options or maybe indexes into an array or... Whereas I use structures, to group together a set of variables to be referenced together. i.e. sort of like a class without member functions. There are several examples of structures where the order and packing are important. Examples of this can be found in the kinetis.h file. Like the layout of I2C registers:
Code:
typedef struct {
	volatile uint8_t	A1;
	volatile uint8_t	F;
	volatile uint8_t	C1;
	volatile uint8_t	S;
	volatile uint8_t	D;
	volatile uint8_t	C2;
	volatile uint8_t	FLT;
	volatile uint8_t	RA;
	volatile uint8_t	SMB;
	volatile uint8_t	A2;
	volatile uint8_t	SLTH;
	volatile uint8_t	SLTL;
} KINETIS_I2C_t;

Likewise there are places in that file where they use enums, like the IRQ Numbers... The interesting question even in this file is when do you use enum versus separate #defines. Again the enum is used to define the IRQ numbers, but right after this the use a lot of #define statements to define the DMAMUX_SOURCE... which could have also been done with an enum.

Sometimes the order of items in a structure is not important and other times it is. Sometimes as part of a structure I will include one or more enum types as members.

As for enum being preferred? Not sure. Again probably depends on context. Lot of places recommend not using what I would call Naked enums as they polute the name space. They instead recommend putting them into a name space, example ROS: http://wiki.ros.org/CppStyleGuide#Enumerations

Maybe it depends on the phase of the moon ;)
 
enums are used to assign values (typically unique values, although you can force specific values if you wish) to meaningful names that make your code easier to understand. They can be a data type of their own if you declare one as a variable, but they don't have to be.

For example, if you wanted to support different sensor types you might declare an enum such as

enum SENSOR_TYPE
{
TEMPERATURE_SENSOR,
PRESURE_SENSOR,
};

the rules are simple,
1. the first value specified has value 0 (unless you force a specific value). In this example TEMPERATURE_SENSOR has value 0
2. all other values are one greater than the previous (unless you force a specific value). In this example PRESSURE_SENSOR has value 1.

So far you haven't used any memory, until you declare an instance of one. e.g.

enum SENSOR_TYPE my_sensor;

The underlying type of an enum is an int, so now you've used however many bytes an int is (for your complier). Although as others have stated, you can usually force it to be smaller than an int, usually by a compiler optimisation setting.


structs are used to group data items that logically go together. e.g.

struct TEMPERATURE_SENSOR_PARAMETERS
{
int i2c_channel;
short int i2c_address;
};

Again, you haven't used any memory until you declare one. e.g.

struct TEMPERATURE_SENSOR_PARAMETERS my_temp_sensor_params;

So my_temp_sensor_params is the size of one int and one short int, however as others have said, you do need to be aware of padding. You may lose some memory due to padding both because of the order you declared the different sized elements within the struct, and depending on what come immediately after the instance of the struct in memory. The compiler will align each element to an address that is divisible by the width of its data type. So, to use the minimum amount of memory, declare the largest data types first, so on and so forth, with the smallest data elements last in the struct.

e.g.

struct bmxConfig {
uint16_t dig_T1, dig_P1, dig_H4, dig_H5;
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9, dig_H2;
uint8_t dig_H1, dig_H3, digH6;
};

is better than

struct bmxConfig {
uint8_t dig_H1, dig_H3, digH6;
uint16_t dig_T1, dig_P1, dig_H4, dig_H5;
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9, dig_H2;
};
 
Thanks everyone! I tried reading about them, but I wasn't really grasping all of it. The example provided above esp. helped clear it up for me.
 
Status
Not open for further replies.
Back
Top