Author Topic: Forcing enum to be of a specific size  (Read 614 times)

0 Members and 1 Guest are viewing this topic.

Offline ricko_uk

  • Frequent Contributor
  • **
  • Posts: 728
  • Country: gb
Forcing enum to be of a specific size
« on: June 12, 2021, 12:02:49 am »
Hi,
in C, is there a way to force an enum to be of a specific size (i.e. uint32_t or uint16_t)?

If not in C, What about C++?

Reason for asking is to make it the size of the micro's architecture to ensure that any change to it is an atomic operation (without having to disable interrupts or using critical sections).

Thank you :)
« Last Edit: June 12, 2021, 12:19:22 am by ricko_uk »
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2105
  • Country: us
Re: Forcing enum to be of a specific size
« Reply #1 on: June 12, 2021, 12:21:39 am »
You can used the "packed" attribute on compilers that support it, for example gcc: https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html

However this doesn't let you specify a particular size, just that it should use the minimum size that will contain the enumerated values.

Alternatively, since enums in C are not really a storage type unto themselves and are basically just defined constants with slightly nicer syntax, you can store them in whatever integer type you want provided it's large enough for the largest value. Enum values are guaranteed to start at 0 and increment by one unless another value is specified, so your max value will be equal to the number values less one unless you specify differently.
 
The following users thanked this post: ricko_uk

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 7191
  • Country: fr
Re: Forcing enum to be of a specific size
« Reply #2 on: June 12, 2021, 02:09:17 am »
Alternatively, since enums in C are not really a storage type unto themselves and are basically just defined constants with slightly nicer syntax, you can store them in whatever integer type you want provided it's large enough for the largest value. Enum values are guaranteed to start at 0 and increment by one unless another value is specified, so your max value will be equal to the number values less one unless you specify differently.

Yes, if you're using C, as was discussed in another thread, enums are not type-checked anyway, so using them as a type for declaring variables/parameters is useless (except for code documentation reasons). So you can use enums to define your constants, and then use another type for actually storing the value.

 
The following users thanked this post: ricko_uk

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2105
  • Country: us
Re: Forcing enum to be of a specific size
« Reply #3 on: June 12, 2021, 02:58:35 am »
Also, there's unlikely to be a significant downside to using a type that is smaller than native, so if you can use an 8 bit int to hold the values you need then you can just use that on all architectures and be done with it.  There may be a *small* performance penalty for smaller sizes on more complex architectures (like x86), but it's unlikely to be enough to worry about, and there should be no difference on Cortex M. 

One thing you may want to do is typedef the storage type you want to use separately from the enum.  You can still typedef the enum if you want.  Typedefing the storage type won't give you any additional type safety (neither will the enum itself!), but it will make it clear that the size is chosen deliberately, and if you need to change that size at any point (because you've added a bunch of enum values, or you have some corner case where the size does matter) you're only changing it in one place.  You'll see this in libraries for these exact reasons.
 

Offline Tagli

  • Contributor
  • Posts: 27
  • Country: tr
Re: Forcing enum to be of a specific size
« Reply #4 on: June 12, 2021, 05:00:03 am »
In C++, you can choose the underlying type for both classical enums and enum classes.

Code: [Select]
enum class Number : uint8_t {Zero = 0, One = 1, Two = 2};
Gokce Taglioglu
 
The following users thanked this post: hans, ricko_uk

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 7191
  • Country: fr
Re: Forcing enum to be of a specific size
« Reply #5 on: June 12, 2021, 04:49:33 pm »
In C++, you can choose the underlying type for both classical enums and enum classes.

Code: [Select]
enum class Number : uint8_t {Zero = 0, One = 1, Two = 2};

I don't know enough C++ for judging if this is right or not. If anyone can tell which C++ std supports that? But if so, that is one nice feature.
 

Offline Tagli

  • Contributor
  • Posts: 27
  • Country: tr
Re: Forcing enum to be of a specific size
« Reply #6 on: June 12, 2021, 05:07:07 pm »
Gokce Taglioglu
 
The following users thanked this post: hans, newbrain, SiliconWizard

Offline ricko_uk

  • Frequent Contributor
  • **
  • Posts: 728
  • Country: gb
Re: Forcing enum to be of a specific size
« Reply #7 on: June 12, 2021, 06:31:11 pm »
Thank you all! :)

 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 1493
  • Country: es
Re: Forcing enum to be of a specific size
« Reply #8 on: June 12, 2021, 08:59:48 pm »
Probably everyone knows this from 1st of programming... Anyways, in normal C you can always cast the enum to an int of any size.
Ex. :
Code: [Select]
typedef enum{
    opt_disable,
    opt_enable,
    opt_reset,
    opt_auto
}options_t;

options_t opts;

int main()
{
    if ((uint8_t)opts == opt_disable){
        printf("Option: Disabled, enabling....\r\n");
        opts = opt_enable;
    }
    return 0;
}

Also gcc has it's own "attributes":
https://gcc.gnu.org/onlinedocs/gcc-3.3.2/gcc/Type-Attributes.html#Type%20Attributes
Hantek DSO2x1x            Drive        FAQ
Stm32 Soldering FW      Forum      Github      Donate
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2105
  • Country: us
Re: Forcing enum to be of a specific size
« Reply #9 on: June 12, 2021, 09:49:15 pm »
I'm not sure what you're expecting the cast to do here?  Casting `opts` to uint8_t isn't going to change the allocated storage size.  The only way to do that is to declare `opts` as `uint8_t` (or whatever) instead of `options_t`, like I said earlier.  Using the packed attribute would affect the storage size of anything declared as `options_t`, but depends on the range of the enumerated values.  The cast won't meaningfully affect the comparison unless opts is stored at >8 bits and has bits set beyond the low byte, in which case it may break the comparison (depending on what you're trying to achieve).  Integer promotion rules will still apply as well.  ARM for example has zero- and sign-extension and word/half-word/byte load and store instructions so when required the compiler can transform 8 bit values into 32 bit values and vice versa as part of a load/store with no penalty and it'll be atomic as long as they're aligned.
« Last Edit: June 13, 2021, 05:59:35 am by ajb »
 
The following users thanked this post: newbrain


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf