The obvious thing I should've learned 5 years ago

Programming, for all ages and all languages.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Combuster »

And people don't use it because GCC does not accept restrict by default. (it defaults to the '89 standard, you'll need to pass --std=gnu99 or similar for it to work)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Synon
Member
Member
Posts: 169
Joined: Sun Sep 06, 2009 3:54 am
Location: Brighton, United Kingdom

Re: The obvious thing I should've learned 5 years ago

Post by Synon »

Combuster wrote:And people don't use it because GCC does not accept restrict by default. (it defaults to the '89 standard, you'll need to pass --std=gnu99 or similar for it to work)
It also seems to increase executable size... or maybe that's just passing --std=c99. I had a 19 KiB file go up to about 40 when I tried using restrict on my malloc()ated pointers (of which, I had three).
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Solar »

earlz wrote:I think the reason most people don't know about restrict is that it wasn't (still isn't?) included in the C++ standard...
It's high time they get that C++ standard through the door. Some things C99 introduced are sorely lacking from the C++ standard. But lo, what a beast they have to standarize, compared to the very compact C99 standard.

I openly admit that there are several corners in the C/C++ standard I know very little about. Basically, I know they exist, but not much more.

I know pretty well what 'mutable' is for, but haven't used it more than twice. I know 'explicit' exists, and remember some of the details, but would have to look it up before using it with confidence. C99 variable length arrays... I know they exist, but no more.

Nothing of that really bothers me. I almost never come across these constructs, and looking them up is a matter of seconds.

What really does bother me is that I never got beyond the beginner's phase with regards to C++ templates / STL. I know enough to get the work done, a functor isn't an unknown beast to me, but I know that I don't know the better half of the STL half as well as I should. (Thank you, Bilbo Baggins! :twisted: ) I have to look up the details of ptr_fun() every time I come across it, and stuff like compose1( negate< double >, ptr_fun( fabs ) ); leaves me scratching my head and digging through references... at least I know what to look for, and eventually figure it out, and am usually the one my co-workers ask for help when they come across one of those, but I still feel that's my blind spot.

Too bad I don't get much experience in that regard either. Office code is far too dumb to use constructs like that, and my hobby project is C, not C++... :?
Every good solution is obvious once you've found it.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Colonel Kernel »

A lot of the stuff in <functional> is a hack to overcome the lack of lambda expressions. Hopefully the addition of lambdas in C++0x will make such features more accessible to everyone.

What scares me in C++0x is all the new stuff about rvalue versus lvalue references, "move constructors", "move assignment operators", etc... It seems to me like we need to tell the compiler way too much information for the sake of optimization. :P
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: The obvious thing I should've learned 5 years ago

Post by qw »

Well, "register" was added for the sake of optimization from the very beginning. I have mixed feelings about this. You could add a hundred keywords to a language to tell the compiler how to optimize, but they don't contribute to the algorithm at all.

(I never use "register". I do use "const" and "volatile" however.)
midir
Member
Member
Posts: 46
Joined: Fri Jun 13, 2008 4:09 pm

Re: The obvious thing I should've learned 5 years ago

Post by midir »

earlz wrote:So I'm a self-taught C programmer.
[...]
Been programming C for over 5 years now and I'm just NOW figuring out that there is a `continue` keyword!?
Same here. It was a jubilant moment when I discovered it. Actually I discovered it in PHP first, and thought "What a great new idea!", and later discovered that C had had it all along too, for decades. :roll:

It's a really handy way to "filter" a loop without using (possibly several) nested ifs, so then you can do something complex in the loop at a lesser level of indenting.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Solar »

You "continue" guys hopefully remember to comment its usage well in your code. The ladder of evil: continue, break, goto. :twisted:
Every good solution is obvious once you've found it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Combuster »

The ladder of evil: continue, break, goto.
I'd put break above continue or goto. Especially in switch statements, you can't really get away without them. You can do without continue with little second thought. And goto, well...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Solar »

Using break in switch statements is excused. As for while loops, on the other hand... :twisted:
Every good solution is obvious once you've found it.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: The obvious thing I should've learned 5 years ago

Post by qw »

Combuster wrote:And people don't use it because GCC does not accept restrict by default. (it defaults to the '89 standard, you'll need to pass --std=gnu99 or similar for it to work)
GCC does support the non-standard "__restrict__" since (I think) version 2.95.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by Solar »

...but using -std=c99 is the way to go. ;-)
Every good solution is obvious once you've found it.
Synon
Member
Member
Posts: 169
Joined: Sun Sep 06, 2009 3:54 am
Location: Brighton, United Kingdom

Re: The obvious thing I should've learned 5 years ago

Post by Synon »

Solar wrote:Using break in switch statements is excused. As for while loops, on the other hand... :twisted:
Depends where it is.

This is a bad use:

Code: Select all

while (true) {
    blahBlahBlah();

    if (condition)
        break;
}
and so is this (something like this actually appeared in Beej's Guide to Network Programming) (IMO):

Code: Select all

while (condition) {
    if (this)
        continue;

    if (that)
        continue;

    if (the_other)
        continue;

    break;
}
It's clear what it's doing but it's still a little ugly.

Would a valid use of break be to neaten up the while statement's condition:

Code: Select all

while (true) {
    /* ... */

    if (condition_A_which_takes_up_a_lot_of_space ||
        (condition_B_which_takes_up_a_lot_of_space_too &&
         condition_C_which_takes_up_even_more_space_than_A_and_B))
        break;
}
?
IMO, yes. It's still ugly, but to put that in the while loop's clause would be uglier. And I have had to do that once... it was a be-all, end-all line input function. I don't have it any more because the hard disk on the computer I wrote it on is dead. Basically it was to automate doing this:

Code: Select all

printf("What option do you want to pick? [A/B]: ");
fgets(buf, bufsz, stdin);
and it evolved into

Code: Select all

get_input(buf, &options);
options would be an instance of struct gi_opts which said
* What stream to get the input from
* What options to display (A, B, C, Y, N or anything you wanted)
* What to use to divide the options (e.g. "/" or "|") which I removed (unnecessary)
* What to use to surround the options (e.g. "[" would be matched with "]", etc.) which I also removed for the same reason as above
* Which option was the default (-1 for none)
* What to do on invalid input (could be GI_OPTS_EXIT, GI_OPTS_REITER and/or GI_OPTS_PROMPT; the first two being mutually exclusive)
* Max amount of times to reiterate on invalid input (if GI_OPTS_REITER was chosen)
* A prompt to display

Anyway I had to do that in the while loop for the __get_input(char* buf, FILE* stream) function.
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: The obvious thing I should've learned 5 years ago

Post by AndrewAPrice »

If now even break and continue are considered bad since they break execution flow, what are your feelings about a 'return' that is not part of the last statement in a function?

Sometimes it may not be so simple to avoid without making it messy, such as in this example:

Code: Select all

while(condition1)
{
   if(condition2)
   {
       // heavy logic

       if(condition3)
           break;

       // heavy logic
       if(condition4)
           break;

       // heavy logic
   }

   // heavy logic
}
vs

Code: Select all

bool done = false;
while(!done)
{
    if(condition1)
    {
         // heavy logic
         if(condition3)
             done = true;
         else
         {
             // heavy logic
             if(condition4)
                 done = true;
             else
                 // heavy logic
         }
    }
    if(!done)
    {
        // heavy logic
    }
    done |= condition1;
}
My OS is Perception.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by JamesM »

Personally I use "early-exit" operators as much as possible in order to reduce the amount of nesting needed and therefore make code easier to read. That means break, continue, return.

They don't impact performance and it's blatantly obvious what the intention is. If it improves my code's readability, it's worth it. YMMV.
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Re: The obvious thing I should've learned 5 years ago

Post by earlz »

JamesM wrote:Personally I use "early-exit" operators as much as possible in order to reduce the amount of nesting needed and therefore make code easier to read. That means break, continue, return.

They don't impact performance and it's blatantly obvious what the intention is. If it improves my code's readability, it's worth it. YMMV.
Yup, I believe Linus or some famous coder put it something like "Using break and continue is bad cause it's basically a disguised goto. But if you have over 3 levels of indentation, your screwed anyway"
Post Reply