On 28/05/14 21:52, Jonathan S. Shapiro wrote: > So in both cases an enum can be smaller than an int according to > implementation-defined criteria. The more substantive difference is that > in C++ an enum can be /larger/ than an int.
The text you quoted doesn't seem to imply that enums can't be larger than int in C either. However, there is something more fundamental here: does GLib aim to be portable to arbitrary ISO C platforms (including oddities like 36-bit bytes or sign&magnitude arithmetic), or to the narrower set of platforms that people actually use in the real world? If the former, language lawyering about sizes of enums is appropriate. If the latter, we can add a static assertion that sizeof (small enum) == sizeof (int) and get on with our lives, and worry about what the standard says if we find a real, relevant platform where the static assertion fails. In practice, I suspect that in relevant compilers, all enums whose values fit in the range INT32_MIN to INT32_MAX (inclusive) are the same size as int. ISO C allows compiler to break that assumption, but those that do would break code that works fine in other compilers, making the compiler look bad, for no significant benefit. I conjecture that such compilers are not popular. > In practice, the "smaller than int" issue isn't a concern at parameter > passing, where parameters are widened to a full machine word in any > case. More precisely, ISO C's "usual promotions" guarantee to widen smaller-than-int parameters to int. > Then there are structure alignment and offset assumptions. ... > I don't see (offhand) what value the static assertion about > enumeration size is giving us in regards to this issue It doesn't solve anything in that respect; if people assume "Foo.bar starts 8 bytes after the start of Foo" (or whatever) then they should be replacing that assumption with uses of sizeof(), G_STRUCT_OFFSET() and something analogous to alignof(); or at the very least, adding a G_STATIC_ASSERT (G_STRUCT_OFFSET (Foo, bar) == 8) as executable documentation of their assumption. For compatibility with compilers with poor C support like MSVC, GLib is written in C89, which doesn't have alignof() and offsetof() - but it does have G_STRUCT_OFFSET(), and code internal to GLib can use _g_alignof() to get an equivalent of alignof(). I didn't make it public API because I only needed it internally for static assertions, I wasn't sure that it was 100% portable. By suggesting that static assertion, I was only trying to solve enum extension. "When I make this reasonable-looking change between libfoo 2 and libfoo 2, I don't want it to be an ABI break" is quite important to anyone who cares about ABI. > Next there are "unholy overlays", by which I mean places where somebody > has tucked items of unspecified size and alignment into a union from > which they try to re-extract them using some other "leg" of the union. > THAT's just bad code, and it needs to be fixed as we find it. Unions solve alignment, in fact (the union is as strictly-aligned as its most strictly-aligned member), although you still need to worry about size when using type-punning. > Meanwhile, there is a preemptive way to /force/ the compiler to choose > "at least int" as the enum size: > > enum GLogLevel { > ... existing, expected values ... > _require_int = INT_MAX > } > > This works because the compiler is now required to choose an underlying > integral type that will hold INT_MAX. The problem with doing this is > that it will break ABI compatibility on any platform that > /currently/ encodes GLogLevel as a char. I'm actually not aware of any > compiler that does this, but it would probably be a good idea to check > before making this change and accidentally breaking things. The static assertion would trip on exactly those platforms. My suggestion: just add the static assertion and see what happens. If it succeeds on all relevant platforms, no harm done. My intuition is that this is what will happen, because real-world CPUs get performance benefits from only dereferencing word-aligned pointers, and a substantial amount of real-world code blindly assumes int-sized enums, so there is selection pressure on compilers to make enums consistently int-sized if they could have been smaller than int. If it fails on some platform, then the GLib maintainers have to choose whether breaking ABI on that platform now is a worthwhile sacrifice to be able to add enum members without breaking ABI in future. S _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-devel-list