5 ms·
Plan9 compiler extensions in gcc 4.6
- grifaton 16y agoCan somebody explain the significance of this to me?
- ramchip 16y agoIf I understand correctly, GCC now has an extra switch to support some additions to regular C that the Plan 9 compiler offers related to the manipulation of anonymous fields in a structure. I don't think it has much significance for the vast majority of C programmers out there. I'm not sure why this is first place on the front page, to be honest...
- pmjordan 16y agoIt would have a positive effect on the readability and conciseness of our (SSDCache) code if we could actually use compilers supporting this. Unfortunately, we're stuck with older versions of GCC for the foreseeable future, and probably MSVC when we port to Windows. In hindsight I'm wishing we'd spent some time up-front getting to grips with something like SC [1] for generating C code from something slightly higher level to avoid some of the language's shortcomings that make the code overly convoluted. (some kind of usable closure-like mechanism would be fantastic, for example - callback-based asynchronous I/O isn't particularly fun in C) [1] http://super.para.media.kyoto-u.ac.jp/~tasuku/sc/index-e.html http://super.para.media.kyoto-u.ac.jp/~tasuku/sc/index-e.htm...
- rm445 16y agoThere's a lot of residual good will for Plan 9, because of the people involved, and because of the way many of its good ideas have work their way into other OSes (despite Plan 9 itself's relative lack of success). So ideas from Plan 9 will always have an audience. As for top of the front page, it's just how things bubble up and down, no cause for alarm.
- pmjordan 16y agoThe stuff described on the first part of that page has been supported by GCC for ages. It's useful where structs and unions are deeply nested, e.g.: enum MyStructType { MyInt, MyFloat }; struct my_struct { enum MyStructType type; union { struct { int my_int; } as_int; struct { float my_float; } as_float; } d; }; To get to the actual data, in standard C89/99 you need to do this: struct my_struct* s = /* ... */; if (s->type == MyInt) printf("%i\n", s->d.as_int.my_int); /* <- !!!!!! */ else printf("%f\n", s->d.as_float.my_float); /* <- !!!!!! */ With the extension, the inner union and struct members are added to the outer struct/union's namespace: enum MyStructType { MyInt, MyFloat }; struct my_struct { enum MyStructType type; union { struct { int my_int; }; struct { float my_float; }; }; /* note: no name */ }; Now the access code is much nicer: struct my_struct* s = /* ... */; if (s->type == MyInt) printf("%i\n", s->my_int); /* <- !!!!!! */ else printf("%f\n", s->my_float); /* <- !!!!!! */ The second part extends this to typedefs, while the third part, the Plan9 addition (which is presumably the reason for the HN submission) gives you an implicit struct pointer conversion for structs composed of other structs, a bit like C++'s implicit pointer conversion for inheritance. The page has an example of this already: struct s1 { int a; }; struct s2 { struct s1; }; extern void f1 (struct s1 *); void f2 (struct s2 *p) { f1 (p); } This is how you'd normally have to do it: struct s1 { int a; }; struct s2 { struct s1 my_s1; }; // <- note non-anonymous struct field extern void f1 (struct s1 *); void f2 (struct s2 *p) { f1 (&p->my_s1); } // <- my code is always littered with this idiom All of this might not seem like much, but complicated data structures really aren't a forte of the C syntax. A bit of sugar alleviates at least some of the endless repetition.
- pmjordan 16y agoThe last part is pretty cool (the first bit has been supported by GCC for years), though it would be even more helpful to be able to do the reverse concisely - convert a pointer to the contained struct to a pointer to the containing one. In my C code I invariably use (something similar to) the container_of() macro used in the Linux kernel [1]. The primary use is in callbacks associated with a particular object that can be embedded in larger structures. Right now, say a library I'm using exposes this: struct lib_struct { int foo; char* bar; }; typedef void (*lib_callback)(struct lib_struct*); extern void lib_fn(struct lib_struct* obj, lib_callback cb); If I want to use that in one of my own data structures: struct my_struct { struct lib_struct lib_st; int my_own_data; }; static void my_callback(struct lib_struct* lib_st) { // plan9 extension does not appear to help here... struct my_struct* me = container_of(lib_st, struct my_struct, lib_st); printf("%i\n", me->my_own_data); } /* elsewhere... */ struct my_struct* m = /* ... */; // ... though it would here: lib_fn(&m->lib_st, my_callback); It'd be handy to be able to condense the container_of line somewhat, while maintaining (some) type safety. [1] http://www.kroah.com/log/linux/container_of.html http://www.kroah.com/log/linux/container_of.html - I use a similar macro that preserves NULL pointers.
- coliveira 16y agoThese features may be used to program in a more OO style without the notion of classes. For example, one case use the embedding of fields to have a similar effect to inheritance. Similarly, one can pass pointers to objects that contain a type as if it was the type itself, which is the same thing that inheritance allows. Of course, here there is no difference between containment and inheritance, you can use it as you desire.