Well, this was supposed to be another "Random" post, but as the typing went on, it grew quite long, so I've decided to post this as a normal post. So, today's post will be about some new (i.e. new for me) extensions in GCC I've dig up, and a random rant on what I still miss in C/C++ (and no, I don't have templates of templates of templates in mind ;f).

The first GCC extension on the list is the binary constant, e.g.:
int a = 0b01010101;
Yees, finally I won't have to convert binary numbers to hex (well actually I already do it quite fast, so... But! Better late than never I guess).

The second extension on my list is the Thread Local Storage in-language support. So, finally the gcc/g++ users (including MinGW) can operate on TLS without having yo use the system API, hence, more portability between e.g. Linux and Windows systems :)
In gcc/g++ you use TLS like this:
__thread int asdf;
As a reminder, you can also use in-language TLS in Visual C++, however the declaration is a bit different (though, still similar):
__declspec(thread) int asdf;
Well, C++0x will have TLS support covered by the standard, and there will be yet another different keyword to do that: thread_local.

I've tested the above extension (code + output are on the bottom of the post) on MinGW gcc 4.4.0, however it didn't work properly, i.e. the variable was declared OK using the __thread keyword (i.e. there was no "undeclared __thread" error), but it was still treated as a normal global variable. After googling a bit I found an enigmatic note regarding MinGW GCC 4.4 saying that "keyword __thread is honored" (honored != supported?). Also, I've founf Tls* imports in the generated executable, but still, it didn't work (maybe it wasn't implemented properly yet?).
Well, the end of this story is quite easy to predict: after upgrading to MinGW GCC 4.5.0 everything started working just fine (btw, I found the new mingw-get installing quite cool) :)

OK, another extension! Looks like GCC gained support for the fixed point variables and radix 10 floating points (a step to conform the revised IEEE-754-2008 standard I would guess).
Well, I didn't yet play to much with these, so maybe I'll write something when I finally get to play with them :)

So many new extensions! But still, I miss two things:
1. multiple-level break, that could jump out of N nested-loops at once
2. a break for an stand-alone and if/else blocks of code (a "weak-break")

For those who are not familiar with N-level breaks or labeled blocks of code, the first item on the list is related to a code like this:
while(a) {
 while(b) {
   if(c) break_out_of_both_loops;
 }
}

Well, in C/C++ you cannot break out of both loops at once using just the break instruction. Nope, sorry. You have to emulate this behavior by using one of these fairly known tricks:
1. goto to a label declared after both loops - pretty straight-forward, but... let the anty-goto flames begin! ;)
2. throw (some kind of) an exception and catch it after the loops - well, not everybody likes throwing stuff, nor everybody can actually do it; additionally, some kinds of exceptions are rather expensive
3. move both loops to an external function and use return to jump out of both loops - the code grows big, you have to pass the variables again, and create another function...
4. move only the internal loop to an new function, and return false if one wants to jump out of the second loop at exit (if(!func()) break) - same above.
5. at break, make the 'a' condition to be unmet (e.g. if 'a' is 'a < 10', make a = 10) - not really elegant, and you can introduce some bugs into the code, even if not now, than in the future when someone changes the 'a' condition; also, if 'a' relies on some function calls, it gets reallly tricky.
6. declare a flag before the internal loop, and test it after the loop; if the flag is set, do a break (e.g. bool run_away = false; while(b) { if(c) { run_away = true; break; } } if(run_away) break;) - this is the most elegant emulation I can think of, alas, you have to introduce another variable :(
And so on...

Personally, I would like the code blocks to have an optional name (like they do e.g. in Java). This could look like this:
while(a) petla_zew: {
 while(b) {
   if(c) break petla_zew;
 }
}

Another idea is break <N>, where <N> is the number of loops to jump out of (in out example we should use break 2). Well, but this could cause some bugs in the future, especially when someone changes layout order of the nested loops and forgets to change the <N>.

Well, maybe someday :)

The second thing I've placed on the list is a weak break, that can just to the and of any (i.e. not only for/while/do loops) block of code, e.g. free standing { } or the if(c) { }.
For example, I would like the jump out of the if() block here a little earlier:
if(a) {
 some_code;
 if(b) break_out_of_external_if;
 some_code;
}

Well, you cannot do that straight-forward, and you have to emulate it once again, e.g. using goto and labels (food for the goto flame war ;p) or changing the if block into a while block with an additional break at the end:
while(a) {
 some_code;
 if(b) break;
 some_code;
 break; // additional break to maintain the code logic
}

Of course, if this code had some additional if(c) that jumped out of an external loop, this would lead us to the first problem.

And so I add a weak break to my personal language feature wish list :)

Btw, perl has another interesting construct from the break/continue family - redo. Worth taking a look.

Also MSM on the Polish-side of the mirror mentioned a great legacy mechanism (from Fortran) called COME FROM - this is my new favorite jump-like instruction! Ever! :)

Thats that.

Attachment 1 - experimental code for testing __thread:
#include <stdio.h>
#include <windows.h>

static __thread int var;

DWORD WINAPI MyThread(LPVOID lpParameter)
{
 int param = (int)lpParameter;

 printf("MyThread initial var:\t\t%i\n", var);
 var = param;
 printf("MyThread var at end:\t\t%i\n", var);  

 return 0;
}

int main(void)
{
 HANDLE th;

 var = 13;

 printf("Main initial var:\t\t%i\n", var);
 
 th = CreateThread(NULL, 0, MyThread, (LPVOID)37, 0, NULL);
 WaitForSingleObject(th, INFINITE);
 CloseHandle(th);

 printf("Main after MyThread finishes:\t%i\n", var);

 return 0;
}

Incorrect output (MinGW gcc 4.4.0):
Main initial var:               13
MyThread initial var:           13
MyThread var at end:            37
Main after MyThread finishes:   37

Correct output (MinGW gcc 4.5.0):
Main initial var:               13
MyThread initial var:           0
MyThread var at end:            37
Main after MyThread finishes:   13

Comments:

2010-10-08 17:23:02 = Xion
{
break from if is just awful. The layer of 'abstraction' above a simple jump is just so thin it doesn't seem practical to have it as language feature. Besides, I'm pretty sure it can be avoided altogether by... wait for it... 'else' (and maybe logical negation) :)

As of "strange" language features, 'else' in places other than 'if' count as one, IMHO. I've have already ranted about 'else' after loops in Python being useless and causing bugs; recently I've also discovered 'else' after 'try' blocks. What does it do? Well, it allows to execute a code when the 'try' block did NOT catch any exception, which is unlike 'catch/except' block (executed as a response for excpetion) or 'finally' block (executed always, regardless of exception being thrown). Of course this behavior can be easily achieved via single 'if' and boolean flag.

And yes, COME FROM is brilliant :)
}
2010-10-09 07:44:15 = Gynvael Coldwind
{
@Xion
Hah, I didn't expect your comment on this side of the mirror ;)

As for "else" - insightful, alas, else introduces another nesting layer into the code, so it's just another level of emulating the weak break.
Well, I'm not saying the weak break is something reaaaaaaally needed in the language or reaaaallly useful. I'm just saying that at least three people (that would be Me, Myself and I) would find it useful from time to time :)
Also, maybe the weak break is just an emulation of exceptions which I don't really like? ;) Who knows ;D

As for "else after loops" - woah, good one, didn't know about it. Actually, from what I read (http://pytut.infogami.com/beginners_loops) it's behavior is quite interesting. Allow me to quote:
-- quote --
Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement.
-- end of quote --
Hmm, to tell you the truth, I would expect it e.g. to be executed when the loop condition isn't met even once (e.g. while false: asdf else: this_gets_executed). But hmm, this is even more interesting :)

As for the "being useless" - surely you must agree that there is no law against having useless features in the language :)
As for "causing bugs", you're talking about http://xion.org.pl/2010/09/04/python-wciecia-i-bardzo-wredny-blad/ right?
You might have a point there, however it's the same case as with e.g. strcpy in C/C++ - if you don't know what your doing, you might hurt yourself (think: buffer overflow). So I guess it's a matter of, like always, knowing the characteristics & features of the language (i.e. knowing the potential places which cause the bugs). I'm just not sure if a language feature can be blamed here though...

Nevertheless thanks for another interesting language feature :)

As for COME FROM, I totally agree ;D
}

Add a comment:

Nick:
URL (optional):
Math captcha: 1 ∗ 3 + 1 =