You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have been toying around with implementing FMUs in Rust. Unlike many of c types, rust types must have a fixed size. I have since become aware that FMI3 is going to use the fixed-size defined by C99, which is a very nice improvement.
One thing that may still be problematic is the use of enumerations as arguments and return types.
After doing some research online and looking up the C99 standard, it seems that while enumerations are typically represented using 4 bytes, however, it would be legal for the compiler to represent Fmi2Status as a char, since it can represent all its enumerated values.
#include"stdio.h"/* Type definitions */typedefenum
{
fmi2OK,
fmi2Warning,
fmi2Discard,
fmi2Error,
fmi2Fatal,
fmi2Pending
} fmi2Status;
char (*__kaboom)[sizeof(fmi2Status)] =1;
intmain()
{
printf("size of enum is %d", sizeof(fmi2Status));
}
Compiling with gcc and clang on linux it seems the enum is 4 bytes.
clegaard@ubuntu:~/Desktop/enum_test$ gcc main.c
main.c:20:40: warning: initialization of ‘char (*)[4]’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
20 | char (*__kaboom)[sizeof(fmi2Status)] = 1;| ^
All compilers on my host machine and VM used 4 bytes to represent the type. I seen claims that STM compilers may use the shortest possible type to represent the enum, but I have been unable to reproduce. However, using the fshort-enums flag resulted in the enum being represented using a single byte.
clegaard@ubuntu:~/Desktop/enum_test$ gcc main.c -fshort-enums
main.c:20:40: warning: initialization of ‘char (*)[1]’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
20 | char (*__kaboom)[sizeof(fmi2Status)] = 1;|
In general, it seems that most of the time the enum will be represented as an int, but it is not guaranteed by C99. A solution to this could be to return an int32_t or similar that is able to represent all the enumerated values. This issue may be of value illicitonion/num_enum#21
The text was updated successfully, but these errors were encountered:
While of course C is a broken language, and C enums doubly so, this is only a theoretical problem, as you found out, in that any sane platform ABI will prescribe the size of enum types, otherwise all kinds of interoperability fly out of the window.
This is similar to the problem of padding in structs, where C99 more or less gives implementations leeway to add padding in all kinds of amounts and places, but ABI rules will tighten this down, in order to have any kind of binary portability.
Sure you can force a compiler to deviate from the ABI/sane defaults, but well, you get to keep both pieces, as they say...
Switching to an int type will loose all kinds of error checking/IDE completion support for the benefit of a theoretical problem (especially for return types, which will magically degrade to int anyway on sane ABIs for other unrelated reasons), which is a trade-off I would not like to take (see e.g. KhronosGroup/Vulkan-Docs#124 for a similar decision by the Vulkan people).
BTW for this reason sane foreign language interfaces of languages that must interface with C will take the ABI sizes into account, or let you manually specify them.
PS: Would I wish that broken languages and OSes die out? Sure, but that would leave none of the current crop standing, which would make for a bit of a barren field...
Thank you @pmai for the answer. It seems this is more of a theoretical issue and something you would only have to explicitly deal with in cases where the FMU is not compiled in C.
I have been toying around with implementing FMUs in Rust. Unlike many of c types, rust types must have a fixed size. I have since become aware that FMI3 is going to use the fixed-size defined by C99, which is a very nice improvement.
One thing that may still be problematic is the use of enumerations as arguments and return types.
After doing some research online and looking up the C99 standard, it seems that while enumerations are typically represented using 4 bytes, however, it would be legal for the compiler to represent Fmi2Status as a char, since it can represent all its enumerated values.
I have attached the relevant section of C99 below:
C_enums.pdf
https://stackoverflow.com/questions/366017/what-is-the-size-of-an-enum-in-c
I ran some experiments on GCC and Clang to see how the enum is being represented on different compilers. The code is based on https://stackoverflow.com/questions/20979565/how-can-i-print-the-result-of-sizeof-at-compile-time-in-c
Compiling with gcc and clang on linux it seems the enum is 4 bytes.
All compilers on my host machine and VM used 4 bytes to represent the type. I seen claims that STM compilers may use the shortest possible type to represent the enum, but I have been unable to reproduce. However, using the fshort-enums flag resulted in the enum being represented using a single byte.
In general, it seems that most of the time the enum will be represented as an int, but it is not guaranteed by C99. A solution to this could be to return an int32_t or similar that is able to represent all the enumerated values. This issue may be of value illicitonion/num_enum#21
The text was updated successfully, but these errors were encountered: