Evan Martin (evan) wrote in evan_tech,
Evan Martin

long function names, C subtyping

From gtk-devel, discussing the name of a new function:
> But what an endless function name:
> g_atomic_pointer_compare_and_exchange

37 characters isn't coming anywhere near the record; we just



What C really needs to make GTK less painful is:
  • Though it doesn't apply to this example, C-style subtyping. The C specs guarantee when you have a struct T that has a struct T2 as its first member, a cast from a T2* to a T* is legal¹. Cyclone does this, but you need to make the cast explicit (recall that the language doesn't allow normal casts, so this exception is only because the cast is guaranteed to be safe; you cannot cast, for example, from a T* to a T2* as that is a downcast). GTK is littered with functions like gtk_label_set_text when they could just be "gtk_set_text", which would accept any GtkLabel* or any of its subtypes. If the casting were implicit it'd seem to work magically like C++ (but, importantly, without any late binding / run-time type info).
  • Default arguments. My intuition is that it'd be pretty easy, though, so it's not really interesting.

1 Note, however, that the spec reportedly disallows casts between something like:
struct T {
  int x;
  int y;
struct T2 {
  int x;
  int y;
  int z;
You can use a T2* as an int*, but it's not safe to use it as a T* (because the "y" fields aren't guaranteed to line up). In practice, this does work (compilers will pad these two structs in similar ways), but that's what I'm told the language requires.

You could imagine an alternate world where you just say "as long as everything pads the same they are the same". But my prof came up with a strange construction where it seems that even if the packing lines up with two structures you could get unexpected side effects:
struct T {
  struct T2 {
    int x;
  } t2;
  float y;
struct U {
  struct U2 {
    int x;
    int x2;
  } u2;
  float y;
  int whatever;

Here, alignment of floats on 8-byte boundaries would seem to make these pack the same way, so the y fields would line up.
It would almost seem like you could take a T* to a U and use it safely (that is, no function operating on T*s would modify any of the U2-specific fields).

But in something like this:
struct U u = ...;
struct T t = ...;  /* both t and u are initialized */
struct T *up = (struct T*)&u, *tp = &t;
/* the above cast was safe if you live in a world where "same packing" is safe */
*up = *tp;

What happens to u.x.x2? Is the compiler smart enough to "skip over" those four bytes when copying structures? Somehow I doubt it.
  • Post a new comment


    default userpic
    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.