Slashdot Mirror


Optimizations - Programmer vs. Compiler?

Saravana Kannan asks: "I have been coding in C for a while (10 yrs or so) and tend to use short code snippets. As a simple example, take 'if (!ptr)' instead of 'if (ptr==NULL)'. The reason someone might use the former code snippet is because they believe it would result in smaller machine code if the compiler does not do optimizations or is not smart enough to optimize the particular code snippet. IMHO the latter code snippet is clearer than the former, and I would use it in my code if I know for sure that the compiler will optimize it and produce machine code equivalent to the former code snippet. The previous example was easy. What about code that is more complex? Now that compilers have matured over years and have had many improvements, I ask the Slashdot crowd, what they believe the compiler can be trusted to optimize and what must be hand optimized?" "How would your answer differ (in terms of the level of trust on the compiler) if I'm talking about compilers for Desktops vs. Embedded systems? Compilers for which of the following platforms do you think is more optimized at present - Desktops (because is more commonly used) or Embedded systems (because of need for maximum optimization)? Would be better if you could stick to free (as in beer) and Open Source compilers. Give examples of code optimizations that you think the compiler can/can't be trusted to do."

181 of 1,422 comments (clear)

  1. Ask the compiler... by inertia187 · · Score: 5, Funny

    Programmer: Hey, compiler. How do you like optimizing?
    Compiler: Optimizing? Optimizing? Don't talk to me about optimizing. Here I am, brain the size of a planet, and they've got me optimizing inane snippets of code. Just when you think code couldn't possibly get any worse, it suddenly does. Oh look, a null pointer. I suppose you'll want to see the assembly now. Do you want me to go into an infinite loop or throw an exception right where I'm standing?
    Programmer: Yeah, just show me the stack trace, won't you compiler?

    --
    A programmer is a machine for converting coffee into code.
    1. Re:Ask the compiler... by wizbit · · Score: 2, Insightful

      Or a paranoid, depressed android.

    2. Re:Ask the compiler... by llamalicious · · Score: 5, Funny

      And then the compiler shared his view of the universe with the programmer, who promptly committed suicide.

    3. Re:Ask the compiler... by saden1 · · Score: 2, Funny

      HG2G has got to be the best book on the planet. Here is my favorite dialog in the book.

      --

      -----
      One is born into aristocracy, but mediocrity can only be achieved through hard work.
    4. Re:Ask the compiler... by pboulang · · Score: 2, Insightful

      Tighter code? is that how you are defining optimized? Hmmm... I beg to differ.

      --

      This comment is guaranteed*

      *not guaranteed

    5. Re:Ask the compiler... by bonniot · · Score: 2, Informative
      Oh look, a null pointer... Do you want me to go into an infinite loop or throw an exception right where I'm standing?

      What about using a language where null pointer errors are caught at compile time? Oh, I guess our compiler must have a brain the size of a whole solar system to be able to do that.

    6. Re:Ask the compiler... by Impy+the+Impiuos+Imp · · Score: 2, Interesting

      That's not possible, but a language that doesn't use pointers per se could, and do, exist. Of course they really use pointers behind the scenes, complete with integrity, i.e. NULL checks, so you're not gaining anything.

      Now a processor that zero-checked a pointer on memory deference, auto-built to skip the deference, combined with a language that supported it, would have the check in hardware... ...although zero check is one of the simplest ALU operations, and thus the same speed anyway. Nevermind.

      --
      (-1: Post disagrees with my already-settled worldview) is not a valid mod option.
    7. Re:Ask the compiler... by edf825 · · Score: 3, Funny

      http://www.in.com.au/missing.html ...I just had to post that :)

    8. Re:Ask the compiler... by bonniot · · Score: 2, Informative

      Did you check the links? I'm actually pointing to a specific language where null pointer (OK, references) errors at caught at compile time. It *is* possible.

    9. Re:Ask the compiler... by bonniot · · Score: 2, Informative

      Correct. Although ideally, if it tells you the variable may be null, then there exists some situation where the variable *will* be null. So you better handle this case. Clearly, the problem of reporting an issue exactly in the cases where it will happen is undecidable, so a safe compiler has to be a bit restrictive. In practice, it seems that most cases where it reports a spurious problem is when it depends on the way clients call your code. And in that case, even if it cannot happen now, it could later happen because of a client change, so it's a good idea to handle that case now anyway.

  2. Clear Code by elysian1 · · Score: 5, Insightful

    I think writing clear and easy to understand code is more important in the long run, especially if other people will have to look at it.

    1. Re:Clear Code by normal_guy · · Score: 5, Insightful

      That should be "especially _since_ other people will have to look at it."

      --

      Linux: Free if your time is worthless.
    2. Re:Clear Code by daveho · · Score: 5, Insightful

      I agree 100%. Write code that is easy to understand and modify, then optimize it, but only after you have profiled it to find out where optimization will actually matter .

    3. Re:Clear Code by Tr0mBoNe- · · Score: 2, Interesting

      I agree. I write my code under the assumption (rightly so) that my code will be reviewed by many people in the near future, and then added onto after a bit.

      In fact, working at Research In Motion has shown me how to write better code... sometimes, the most efficient or clever solution are the worst. I would rather see longer variable names, descriptive control structures and a total lack of goto statements. If you write sensible code, and use an optimization setting of 4 or 5, then you will have better programs in the long run. Also, the more complex and "optimized" your code is, the less chance the compilier would be able to optimize it and may even slow it down a little.

      But the biggest thing is to make it readable... I think writing code that executes SO FAST would be useful only in real time systems and large servers.

      Now... back to my realtime system... gotta make those blade servers smoke!

      --
      while(1) { fork(); };
    4. Re:Clear Code by SIGPUNKT · · Score: 2, Insightful
      Amen! If you're not already sweating optimization (i.e., you've got some supremely high-performance code), then it's better to write straightforward code. Especially with C, which has pretty mature compilers.

      Another thing to consider is that compilers for a modern RISC architecture have pretty intense optimization built in just to handle the instruction scheduling (re-ordering instructions to avoid pipeline stalls, etc.) that any trivial optimizations you might make would be "lost in the noise" anyway.

      That said, the big optimizations will always be worthwhile: cacheing results so you don't have to read from a file/database again, using lazy initialization to avoid populating data structures you may not use, validating inputs so you don't get halfway through an expensive operation and then have to roll back the transaction and throw an error, etc. But moving loop invariants? Maybe in a new language with an immature compiler, or a scripting language (just how efficient is PHP, anyway? Python?), but any modern compiler will make that irrelevant.

      --
      Where am I to go, now that I've gone too far?
    5. Re:Clear Code by pz · · Score: 2, Insightful

      This is absolutely true. Even if you are the only programmer who will ever look at the code. 10 years from now, when you're called on to fix a bug in something you wrote, you'll be extra glad that you took the time to write clearly, and comment liberally. Anyone else who comes across your code will thank you as well. And I'm speaking with nearly 30 years' experience as a programmer (and two CS degrees from MIT).

      In particular, unless you have very specific efficiency needs, modern CPUs are more than up to the task for nearly anything we can think of these days, further ameliorating the need for trading optimization against clarity. That said, there still remain applications which are CPU-bound. In such cases where hand optimization makes a difference, I usually first write a clear, general-purpose version of the code to make sure it works correctly. Then, I'll special case highly optimized versions where all bets are off for readability and maintainability, but will retain the clear version for the general purpose case. This does two things: first, it provides a soft intro to the algorithm in unoptimized fasion, aiding future maintenance; second, it provides a benchmark against which performance and correctness of the optimized code can be tested. If code size becomes a serious issue (for example in embedded applications), the clearly written reference code gets put in a comment above the highly optimized code. But in any case, the clear, correct version is retained.

      The importance of clearly written code (and the process of writing code clearly) is difficult to overstate.

      --

      Put my fist through my alarm clock with its ding-dong death inside my ear. - The Blackjacks.
    6. Re:Clear Code by Anonymous Coward · · Score: 3, Insightful

      Naturally. However, the example is retarded. I use the simpler form precisely because it's clearer and more expressive.

      "if (!ptr)" translates perfectly clear into english as "if no (valid) pointer" while "if (ptr==NULL)" involves some spurious special case value that I need to spend extra tinkering with.

      It's like comparing booleans with "if (foo==true)" instead of "if (foo)". If that's better why not go all the way and write "if (((...((foo==true)==true)==true)...==true)==true)" ? For extra clarity you should probably make a recursive function out of it.

    7. Re:Clear Code by smittyoneeach · · Score: 3, Funny

      You mean that we should not strain after a redundant temporary object gnat and swallow a network socket camel?
      If you are caught thinking out of the box again, you will get no dessert!

      --
      Get thee glass eyes, and, like a scurvy politician, seem to see things thou dost not.--King Lear
    8. Re:Clear Code by jallen02 · · Score: 2, Informative

      Not to mention if you write "correct" and cohesive code you can easily optimize it.

      As long as you don't over architect or go to extremes of abstraction your can do some very well abstracted code that pretty nicely separates all of the things that change from the things that stay the same. When you create this kind of separation optimization becomes easier and easier.

      Good (simple) examples are creating a generic interface to sort. You may start off with a simple insertion sort (why bother with heap/quick if you don't need it?). Anyone can understand insertion sort and its fine for relatively small sets of data. Then you expand the scope of the program and realize you need a better sorting algorithm. No problem! You go in and change the behind the scenes sort. Your interface to sort did not change and your program happily works just how it did. You apply this very same idea to as much of the software you write as is reasonable. Separate out data models and logic and displays. Keep each part of the system doing one task and doing it well.

      If the system is written good enough you don't even need anything but high level comments explaining the "big picture" of what is going on. I hate comments that are like the following:

      /* Set foo to 10 */
      int foo = 10;

      Well thank you captain obvious!

      Much better is an explanation over a block of 5-10 lines giving you an idea of what you are trying to achieve. Comment any thing that is not clear, like if your using bitwise shifts to multiply and divide, for example.

      Strive for simplicity :)

      Jeremy

    9. Re:Clear Code by david+duncan+scott · · Score: 4, Interesting
      Yup, that's why your bank throws away all three zillion lines of COBOL every year -- because there's a greater risk in maintenance than in new code.

      I wish I could put my hands on an article I read a couple years back on the code in the Space Shuttle. They go at that code base with an attitude that makes the average paranoid look happy-go-lucky. In fact, they approach software engineering kind of like other engineers do -- as if lives depended on it. It's old, it's slow, and it works. (Oh, wait, here it is.) That's how code is maintained.

      --

      This next song is very sad. Please clap along. -- Robin Zander

    10. Re:Clear Code by joshdick · · Score: 2, Insightful

      I've heard this very example used many times in the past, and I think it's ridiculous. Any programmer knows that (!ptr) is the same as (ptr == NULL), so what makes you think one is clearer than another?

    11. Re:Clear Code by oliverthered · · Score: 2, Insightful

      I don't see where there is a contradiction, well unless the guy reading you code can't understand a quick-sort, even with enough comments to write a book on the subject.

      The optimisation rules are.

      Good algorithms, beats any optimisation of bad ones hands down.

      The make sure you know what the algorithm does, that way you can possibly minimise work.
      (e.g. a div is just a lot of subtracts and shifts)

      then good 'hints' for the compiler.

      then do it by hand if the compiler it making a mess of things.

      Consider that I could write a 'fast' Word processor in VB3(all interpreted) when compared to one written in C fully optimised, because I make good algorithm choices.

      There's a HSV colour picker in one application that is slow as a dog, they could have used a look-up table and made it possibly a hundred times faster. (near real-time, vs visible delay)

      as far as the code examples.

      I think you should use if(NULL == something), that way the compiler will choke if you type if(NULL = something) by accident.

      some people say just use HeapFree, because it checks nulls and is fast, I say check the null when expected and not when not.

      --
      thank God the internet isn't a human right.
    12. Re:Clear Code by Rei · · Score: 5, Insightful

      An important lesson that I wish I had learned when I was younger ;) It is crazy to start optimizing before you know where your bottlenecks are. Don't guess - run a profiler. It's not hard, and you'll likely get some big surprises.

      Another thing to remember is this: the compiler isn't stupid; don't pretend that it is. I had senior developers at an earlier job mad at me because I wasn't creating temporary variables for the limits of my loop indices (on unprofiled code, nonetheless!). It took actually digging up an article on the net to show that all modern compilers automatically dereference any const references (be they arrays, linked lists, const object functions, etc) before starting the loop.

      Another example: function calls. I've heard some people be insistant that the way to speed up an inner loop is to remove the code from function calls so that you don't have function call overhead. No! Again, compilers will do this for you. As compilers were evolving, they added the "inline" keyword, which does this for you. Eventually, the compilers got smart enough that they started inlining code on their own when not specified and not inlining it when coders told it to be inline if it would be inefficient. Due to coder pressure, at least one compiler that I read about had an "inlinedamnit" (or something to that effect) keyword to force inlining when you're positive that you know better than the compiler ;)

      Once again, the compiler isn't stupid. If an optimization seems "obvious" to you, odds are pretty good that the compiler will take care of it. Go for the non-obvious optimizations. Can you remove a loop from a nested set of loops by changing how you're representing your data? Can you replace a hack that you made with standard library code (which tends to be optimized like crazy)? Etc. Don't start dereferencing variables, removing the code from function calls, or things like this. The compiler will do this for you.

      If possible, work with the compiler to help it. Use "restrict". Use "const". Give it whatever clues you can.

      --
      "Lock and load, Brides of Christ!"
    13. Re:Clear Code by B'Trey · · Score: 2, Informative

      Some experts seem to disagree with you.

      --

      "The legitimate powers of government extend only to such acts as are injurious to others." Thomas Jefferson.

    14. Re:Clear Code by Coz · · Score: 2, Insightful

      Remember - compilers don't care about comments!

      --
      I love vegetarians - some of my favorite foods are vegetarians.
    15. Re:Clear Code by DJStealth · · Score: 4, Insightful

      Take the following example that is clear, but only 1 is considered optimized.

      Lets say you're traversing a 2D array of data (e.g., an image).

      for(x=0; x < width; x++)
      {
      for(y=0; y < height; y++)
      {
      ...
      }
      }

      versus

      for(y=0; y < height; y++)
      {
      for(x=0; x < width; x++)
      {
      ...
      }
      }

      The latter piece of code is just as clear as the first; however, will likely run about 50 times faster than the first, due to caching issues.

      Will the compiler optimize the first piece of code to look like the second? Probably not (tell me if I'm wrong), as there may be a reason to process things in a particular order.

      In addition, the latter piece of code may actually be less clear, as in some cases, it may not read well to do height before width in the for loop.

      As a result, you'll still need to write code thinking about optimization.

    16. Re:Clear Code by Matt+Perry · · Score: 2, Insightful
      An important lesson that I wish I had learned when I was younger ;) It is crazy to start optimizing before you know where your bottlenecks are.
      It's like that saying:

      Rules of Optimization:
      Rule 1: Don't do it.
      Rule 2 (for experts only): Don't do it yet.

      --
      Slashdot: Failed Car Analogies. Amateur Lawyering. Anecdote Battles.
    17. Re:Clear Code by lymc · · Score: 4, Interesting

      Now, let me tell you the flip side of that story. I was working on the Viking Mars Lander program long ago (1976). The code for the lander programs was frozen a year before launch (which itself was a year before landing). Some dozen "books" of the assembly code were created and archived for use when the landers finally landed. All went well for about 6 months after landing. Updates were made and duly entered into the master asssembly listings. After six months of this, the listings were so xed out, and all the margin space used with notes, that errors started creeping in. Finally an uploaded patch wrote over part of the antenna pointing table, and the lander was lost, but for a fortuitious accident which allowed the table to be re-established (with much howling and gnashing of teeth). Sometimes new is better, even if it is painful.

    18. Re:Clear Code by mveloso · · Score: 2, Interesting



      Well, in Java this may speed things up. All instance variable references won't be cached locally. It's been a while since I checked this, but I believe that it's still true. Just something to think about if you're looping a few million times.

      Sometimes it helps, sometimes it doesn't. The only way to really know what your compiler does is to look at the output of the compiler, and understand what all those switches do.

      Now there are some things you can do to optimize your code while you're writing it, but a lot of that is heavily dependent on your platform, runtime, and environment. In general, you should write your code in a straightforward way, then write an optimized version of it later (if you determine it's necessary).

      Of course, the best way to help your optimizer is to write things in the simplest manner possible.

    19. Re:Clear Code by Tony+Hoyle · · Score: 2, Insightful

      Indeed.. the example is totally backward.

      if(!ptr) is 'if not pointer' - which makes perfect sense to any programmer and anyone who has even a passing knowledge of boolean logic.

      I've seen the '== true' and '== false' things around and really hate them as they're not nearly as legible.. Worse is '!= false' and '!= true' - you have to actually stop an think what that means as it's a double negative.

    20. Re:Clear Code by oliverthered · · Score: 2, Insightful

      That should be "especially since _I_ will have to look at it _later_"

      Don't just write nice code for other people to read, write it for yourself.

      --
      thank God the internet isn't a human right.
    21. Re:Clear Code by ArbitraryConstant · · Score: 2, Interesting

      When passing pointers, the "const" thing is a big deal.

      It has to make sure it uses the copy in memory everywhere if anyone else gets a copy of the pointer. That function might keep a copy, pass it around there's no way to know.

      If you use "const" in the function decleration, it can assume no one elsewhere will be changing it.

      Of course, in my always humble opinion using a compiled language at all is a premature optimization most of the time. :)

      --
      I rarely criticize things I don't care about.
    22. Re:Clear Code by lubricated · · Score: 5, Insightful

      well the first thing to optimize is the algorithm. Use a O(n^2) algorithm that does the same job as an O(e^n) algorithm if you can. Algorithmical optimization makes the most difference. I am working on a program who's speed is directly proportional to how how often a particular function is called. Well, I try to reduce calls to this function by various means, no compiler I've sean can optimize an algorithm, only the implementation of it. With that I'm happy to have the compiler do the work.

      --
      It has been statistically shown that helmets increase the risk of head injury.
    23. Re:Clear Code by eric76 · · Score: 2, Informative

      Because of the way the data is stored.

      It is faster to process the data sequentially than to skip around.

      That is especially true if the data elements are small such as chars. You would end up having to fetch the same data from memory multiple times in the processing of one loop compared to only once in the other loop.

    24. Re:Clear Code by drgonzo59 · · Score: 5, Interesting

      Same goes for code that runs on the airplanes (like Boeing passenger aircraft). In fact the developers have to prove that each possible! branch that code could ever take won't lead to unpredictable behavior or crash. If you have 100 independent 'if' statements that is at least 2^100 possibilites. The code they write is very linear, they avoid branching at all cost.

      There is a whole are of study involved in correctness checking, which is related to the SAT (Satisfiability) problem.

      The operating system choice is also interesting. Linux doesn't even come close to what they need. Having device drivers in the kernel is just not a good idea. It needs to have a separation kernel, at least that is the goal. I presently think they use the INTEGRITY operating system by Green Hills, but I could be wrong.

    25. Re:Clear Code by severoon · · Score: 2, Insightful

      At every place I've worked, I've always had a standing bet open to any and all takers. You branch your code and I'll branch mine, you preoptimize and I'll write legible code that sticks religiously to good OO design principles. After the development cycle ends, if a profiling tool proves that your way is better in a significantly demonstrable fashion to the product, you win $100. If not, you owe me $50. (You can hammer out the terms of "significantly demonstrable," but it basically means that the code we're talking about falls into the 20% of the codebase--per the 80/20 rule about where execution flow spends most of its time--and my way is so much more grossly inefficient than yours it actually causes consternation in the end user.)

      Put like this, no one ever takes the bet. It's easy money for me. Even the strongest preoptimization advocates get pretty silent once the discussion is framed this way.

      Here's the thing. Except in certain, specific circumstances, e.g. real-time or embedded high-performance systems, lack of performance comes from bad design 99.9% of the time. If the design of the product accommodates the performance requirements properly, no optimization is usually necessary.

      Does optimization help in these situations? It depends on what you mean by "help". If you mean, does it make it faster, then yes. If you mean, does it make a better product, then the answer is most cases is indubitably: no. Faster, more fragile, less maintainable, and more poorly documented usually means worse for the product. And the kicker is, in most cases it doesn't improve performance in any meaningful way.

      Much better is to approach your architecture and design with an eye towards the specific performance factors and requirements of your product, and design things properly. This will get the big stuff (that you can't usually optimize your way out of anyway). Then somewhere near code freeze, set aside time to do profiling to the extent that gives you a good idea of where the CPU is burning most of its cycles. Usually that's somewhere between 5% and 10% of your code, and usually it's only reasonable to optimize in 5%-10% of that code, and usually there are only opportunities to do intelligent optimization in 5%-10% of that code. (Of course, this doesn't take into account all of the boneheaded code that somehow found its way into the product where just sticking to best practices shows not only markedly better code in terms of performance, but also in every other sense.)

      If you're still finding problems performance-wise, chances are you started off without addressing the right requirements in the first place. Go back to architecture, do not pass Go, do not collect $200.

      --
      but have you considered the following argument: shut up.
    26. Re:Clear Code by say · · Score: 2, Interesting

      no compiler I've sean can optimize an algorithm

      Although I definitely agree with your conclusions, the above sentence is not correct. Most implementations of Scheme, for instance, does a lot of algorithmic optimisations, basically by turning tail-recursion into (functional) iteration when possible.

      These kind of optimizations are extremely effective in some scenarios because it significantly reduces memory use and read/write of memory, and can be illustrated quite easily by turning optimization off in any good Scheme interpreter (like DrScheme).

      --
      Roses are #FF0000, violets are #0000FF, all my base are belong to you
    27. Re:Clear Code by GryMor · · Score: 5, Informative

      It's working on a 2d array of data and is presuming that it is ordered as such:

      123
      456
      789

      data[y][x];

      This, in memory, is:
      123456789

      Similarly, the accsess order for the second loop is:
      123456789

      But for the first one, it is:
      147258369

      The first one hits memory sequentially, which is good for caching as each cache line stores a large chunk of sequential memory.

      Considering hitiing the cache as oposed to hitting main memory is at least 100 times faster, you'll be lucky if the first loop is only 50 times slower.

      This still presumes data stored in the specified order in memory (which is common for image formats, but not the only way things are done).

      --
      Realities just a bunch of bits.
    28. Re:Clear Code by Ninja+Programmer · · Score: 2, Insightful

      Unfortunately, I've posted -- otherwise I would used my mod points to indicate this as a troll or overrated or something.

      The two expressions are semantically identical. There is no difference between the two. So "any programmer" who sees a distinction between the two, is just a defective programmer. Just use the one that follows your "coding conventions" if you've got them, or just use the one you are used to.

      This level of inane minutia is not what I would call "real programming", any more than typing skills are.

    29. Re:Clear Code by John+Hasler · · Score: 2, Interesting

      > There is a whole are of study involved in
      > correctness checking, which is related to
      > the SAT (Satisfiability) problem.

      Knuth:
      "Please don't assume that the above code is error-free. I have only proven it correct, not tested it." (or words to that effect)

      --
      Warning: this article may contain humor, sarcasm, parody, and perhaps even irony. Read at your own risk.
    30. Re:Clear Code by Impy+the+Impiuos+Imp · · Score: 2, Insightful

      ==true and ==false can cause bugs if what you happen to be using isn't a C++ bool but some BOOL that's #defined as an int somewhere.

      Proper naming helps out here.

      Keep in mind people also follow other standards that say DON'T PUT CONSTANTS ON THE RIGHT in a Boolean expression.

      Hence instead of:

      if (!DeviceIsFunctioning)

      you get the "improved" crap of:

      if (false == DeviceIsFunctioning)

      where rules pile on each other to make things even less intelligible. Now throw in some Hugarian munging, and life is grand!

      --
      (-1: Post disagrees with my already-settled worldview) is not a valid mod option.
  3. You should always... by Anonymous Coward · · Score: 5, Funny

    Optimize. Using cryptic, short variable names also shaves valuable microseconds off compile time and run time.

    1. Re:You should always... by FyRE666 · · Score: 4, Funny

      ... and by god don't let me see anyone using comments - comments are the devil's alphabet soup! Every programmer worth his/her salt knows that source code is self documenting...

    2. Re:You should always... by MillionthMonkey · · Score: 4, Funny

      But the code compiles so much faster when you turn it all into comments.

    3. Re:You should always... by holle2 · · Score: 3, Funny
      Found on The Daily WTF http://thedailywtf.com/ShowPost.aspx?PostID=30233
      ------------
      [...]
      $result = mysql_query("SELECT a, b, c, d, e, f, g, h, i, j, k, l,
      m, n, o, p, q, r, s, t, u, v, w, x, y, z, a2, b2, c2, d2, e2, f2, g2,
      h2, i2, j2, k2, l2, m2, n2, o2, p2, q2, r2, s2, t2, u2, v2, w2, x2, y2, z2,
      a3, b3, c3, d3, e3, f3, g3, h3, i3, j3, k3, l3, m3, n3, o3, p3, q3, r3, s3,
      t3, u3, v3, w3, x3, y3, z3, a4, b4, c4, d4, e4, f4, g4, h4, i4, j4, k4, l4,
      m4, n4, o4, p4, q4, r4, s4, t4, u4, v4, w4, x4, y4, z4, a5, b5, c5, d5, e5,
      f5, g5, h5, i5, j5, k5, l5, m5, n5, o5, p5, q5, r5, s5, t5, u5, v5, w5, x5, y5, z5,
      a6, b6, c6, d6, e6, f6, g6, h6, i6, j6, k6, l6, m6, n6, o6, p6, q6, r6, s6, t6, u6, v6, w6, x6, y6, z6,
      a7, b7, c7, d7, e7, f7, g7, h7, i7, j7, k7, l7, m7, n7, o7, p7, q7, r7, s7, t7, u7, v7, w7, x7, y7, z7,
      a8, b8, c8, d8, e8, f8, g8, h8, i8, j8, k8, l8, m8, n8, o8, p8, q8, r8, s8, t8, u8, v8, w8, x8, y8, z8,
      a9, b9, c9, d9, e9, f9, g9, h9, i9, j9, j9, casenum, contype
      FROM gct WHERE casenum = '$aid'");
      while(list($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,
      $m,$n,$o,$p,$q,$r,$s,$t,$u,$v,$w,$x,$y,$z,$a2,$b2, $c2,$d2,$e2,$f2,$g2,
      $h2,$i2,$j2,$k2,$l2,$m2,$n2,$o2,$p2,$q2,$r2,$s2,$t 2,$u2,$v2,$w2,$x2,$y2,$z2,
      $a3,$b3,$c3,$d3,$e3,$f3,$g3,$h3,$i3,$j3,$k3,$l3,$m 3,$n3,$o3,$p3,$q3,$r3,$s3,
      $t3,$u3,$v3,$w3,$x3,$y3,$z3,$a4,$b4,$c4,$d4,$e4,$f 4,$g4,$h4,$i4,$j4,$k4,$l4,
      $m4,$n4,$o4,$p4,$q4,$r4,$s4,$t4,$u4,$v4,$w4,$x4,$y 4,$z4,$a5,$b5,$c5,$d5,$e5,
      $f5,$g5,$h5,$i5,$j5,$k5,$l5,$m5,$n5,$o5,$p5,$q5,$r 5,$s5,$t5,$u5,$v5,$w5,$x5,
      $y5,$z5,$a6,$b6,$c6,$d6,$e6,$f6,$g6,$h6,$i6,$j6,$k 6,$l6,$m6,$n6,$o6,$p6,$q6,
      $r6,$s6,$t6,$u6,$v6,$w6,$x6,$y6,$z6,$a7,$b7,$c7,$d 7,$e7,$f7,$g7,$h7,$i7,$j7,
      $k7,$l7,$m7,$n7,$o7,$p7,$q7,$r7,$s7,$t7,$u7,$v7,$w 7,$x7,$y7,$z7,$a8,$b8,$c8,
      $d8,$e8,$f8,$g8,$h8,$i8,$j8,$k8,$l8,$m8,$n8,$o8,$p 8,$q8,$r8,$s8,$t8,$u8,$v8,
      $w8,$x8,$y8,$z8,$a9,$b9,$c9,$d9,$e9,$f9,$g9,$h9,$i 9,$j9,$j9,$casenum,$contype) = mysql_fetch_row($result))
      [...]
      ------------
    4. Re:You should always... by aixguru1 · · Score: 2, Interesting

      A good programmer who codes in C should be able to understand what is going on. Still it is no substitute for real documentation... Someone should let the folks that enter the IOCCC that they have some of the worst self documenting code I have seen though. It's like trying to read the Xlib programming manuals after a few to many drinks (not recommended and may result in a nasty hangover in the morning).

      --
      root 10956 5164 0 Oct 22 - 0:23 sendmail: rejecting connections: load average: 70 (isn't sendmail just too kind)
    5. Re:You should always... by WindBourne · · Score: 4, Funny

      Sadly, some will even work better.

      --
      I prefer the "u" in honour as it seems to be missing these days.
    6. Re:You should always... by ron_ivi · · Score: 4, Informative
      Using cryptic, short variable names also shaves valuable microseconds off compile time and run time.

      There's nothing wrong with short variable names.

      Thus quoth Linus in the Linux Coding Style guide.

      Chapter 3: Naming

      C is a Spartan language, and so should your naming be. Unlike Modula-2
      and Pascal programmers, C programmers do not use cute names like
      ThisVariableIsATemporaryCounter. A C programmer would call that
      variable "tmp", which is much easier to write, and not the least more
      difficult to understand.

      HOWEVER, while mixed-case names are frowned upon, descriptive names for
      global variables are a must. To call a global function "foo" is a
      shooting offense.

      GLOBAL variables (to be used only if you _really_ need them) need to
      have descriptive names, as do global functions. If you have a function
      that counts the number of active users, you should call that
      "count_active_users()" or similar, you should _not_ call it "cntusr()".

      Encoding the type of a function into the name (so-called Hungarian
      notation) is brain damaged - the compiler knows the types anyway and can
      check those, and it only confuses the programmer. No wonder MicroSoft
      makes buggy programs.

      LOCAL variable names should be short, and to the point. If you have
      some random integer loop counter, it should probably be called "i".
      Calling it "loop_counter" is non-productive, if there is no chance of it
      being mis-understood. Similarly, "tmp" can be just about any type of
      variable that is used to hold a temporary value.

      If you are afraid to mix up your local variable names, you have another
      problem, which is called the function-growth-hormone-imbalance syndrome.
      See next chapter.
    7. Re:You should always... by rjstanford · · Score: 5, Informative

      LOCAL variable names should be short, and to the point. If you have
      some random integer loop counter, it should probably be called "i".
      Calling it "loop_counter" is non-productive, if there is no chance of it
      being mis-understood.


      That last clause is an important one that often gets neglected. In fact, you should never, ever, call a variable loop_counter. That's as bad as pure reverse hungarian - it tells you how its used, not what it means.

      I suggest that, for all non-trivial cases (and I'd prefer to see people err verbosely than compactly), you should use descriptive names. Not loop_counter, but maybe something like curRow? It doesn't have to be long, but at least then as the loop grows over time someone can understand a piece of code more easily than having to scroll back up to check that you are indeed in the "i" loop. Its even more critical when someone comes along and adds a nested (or containing) loop. Or whatever.

      Same with "tmp". If its truly temporary, such as:

      int tmp = getFooCount();
      doSomething(tmp);

      then it should be removed and rewritten as:

      doSomething(getFooCount());

      If its not that temporary, give it a real name. If you insist that it is temporary then you may have a scoping issue - having variables useful but only in part of your function could indicate that your function is doing too much work. If you insist its truly temporary, scope it down: ...
      someRandomCode();
      {
      int foo = getFoo();
      doSomething(foo);
      doSomethingElse(foo);
      }
      moreCode(); ...

      At least now you've guaranteed that it is temporary. Better yet, just name it usefully.

      --
      You're special forces then? That's great! I just love your olympics!
    8. Re:You should always... by Trillan · · Score: 4, Insightful

      With the greatest respect to Linus, but writing a kernel does not make you the authority on programming. It does make you the authority on what particular style you allow in your CVS tree, but that's it.

      I certainly agree that loop_counter is a bad name, though. But rather than use i, I prefer to at least make a note of what sort of objects I'm looping through.

      For instance:

      int taskI;
      int taskCount = GetTaskCount();
      for (taskI=0; taskI<taskCount; taskI++)
      {
      ...
      }

      Code can never be 100% self documenting, but that's no reason not to settle for 0%. Whether you use CamelCase or words_broken_with_underscores is a matter of style, and you should stick with the style of the code base you're working on.

      Anyone who can't or won't work with multiple languages or adopt the necessary style for an existing project is a poor programmer. When you create project, you create the rules. When you work on someone else's project, you follow the rules.

  4. Time to post the famous Knuth quote... by xlv · · Score: 4, Informative

    Donald Knuth wrote "We should forget about small efficiencies, about 97% of the time. Premature optimization is the root of all evil."

    1. Re:Time to post the famous Knuth quote... by Anonymous Coward · · Score: 2, Insightful
      I second that.

      Optimisations at such a low level (especially without profiler evidence to prove it) is often a complete waste of time when the remainder of the code is slow due to crappy algorithm or structure choices.

      ...I remember a guy I worked with wrote a "faster" atol type function. His had less code and did much less. I suggested we profile it to demonstrate is coding prowess. Of course his executed slower than the shipped crt version...his suggestion of taking the crt verson and "hacking out the junk" amused the rest of us for a while hehe (Lee, you know who you are)

  5. Algorithms, Not Stupid Processor Tricks by American+AC+in+Paris · · Score: 5, Insightful
    This is marginally away from the submitter's question, but it warrnats attention:

    The sad truth is that, as far as optimization goes, this isn't where attention is most needed.

    Before we start worrying about things like saving two cycles here and there, we need to start teaching people how to select the proper algorithm for the task at hand.

    There are too many programmers who spend hours turning their code into unreadable mush for the sake of squeezing a few milliseconds out of a loop that runs on the order of O(n!) or O(2^n).

    For 99% of the coders out there, all that needs to be known about code optimization is: pick the right algorithms! Couple this with readable code, and you'll have a program that runs several thousand times faster than it'll ever need to and is easy to maintain--and that's probably all you'll ever need.

    --

    Obliteracy: Words with explosions

    1. Re:Algorithms, Not Stupid Processor Tricks by flynt · · Score: 3, Insightful

      But this would require people to actually get computer science degrees, or have enough self-motivation to read books on algorithms and do the excercises. For most, that's too much to ask, since they cannot see how to apply the theory they learn in school to practice. The ones that can apply the theory are the good programmers. The ones that can't or never learned the theory in the first place probably aren't.

    2. Re:Algorithms, Not Stupid Processor Tricks by jdunn14 · · Score: 2, Insightful

      I agree with you to a point. Do not try to squeeze a couple cycles here and there. Pick the right algorithm, but realize that n vs. n^2 vs. 2^n is not a big deal in 99% of applications. Code it so it works first. Make it go. Then, if it sucks performance-wise, replace those slow algorithms. I've seen too many people, myself included, who try to ensure that they've picked the perfect algorithm for the job, but take 4 times longer to design and write the code. Write the damn thing first. Keep it readable and maintainable first.

      The worst people are those college students completing early algorithms classes. They've just been shown the power of the algorithms, and now they feel that everything must use them. Realistically, if you're working with 10 objects, 100 objects, 1000 objects n^2 often isn't a big deal on a 1ghz+ processor. Learn the tools called profilers that enable you to find where the slow points are and optimize after it basically works. Of course, original design does need to be reasonably modular to allow you to replace algorithms as needed.

      Anyway, just my 2 cents after having not finished some projects because I got too caught up in the algorithm and speed details that on reflection were probably not necessary.

    3. Re:Algorithms, Not Stupid Processor Tricks by lgw · · Score: 2, Insightful

      Wasn't that long ago that every other guy's homegrown 3D engine (software rendering, mind you, this was the 100mhz pentium era) had an ultra-optimized version of bubblesort doing the depth sorting of polygons in a painter's algorithm type affair.

      I certainly hope those people are better educated these days.


      It's almost impossible to beat an optimised assembly bubble-sort when sorting small data sets (up to hundreds, sometimes even thousands). It takes a while for better algorithmic performance to overcome a good static effeciency multiplier.

      It's becoming less of an issue as CPU instruction pipelines get larger (and on-chip cache gets faster), but at that time fitting your entire algorithm into the instruction pipeline could mean execution 10 to 30 times as fast.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    4. Re:Algorithms, Not Stupid Processor Tricks by Flyboy+Connor · · Score: 4, Interesting
      Quite agree, it's about the algorithm, not about the code.

      One of the finest moments in my programming career was when my boss asked me to see if I could gain a speed improvement in a program that surveyed a huge datastore and generated volumes of text from it. This program had to run once a month, and deliver its result in the same month. The program that was originally written, unfortunately, took three months to run (it started out OK, but the data store had grown considerably). They had asked one of our "best programmers" to create a faster version of the program. He did that by reprogramming the entire thing in assembly (you may now understand why managers thought he was one of the best programmers). It took him six whole months to finish the new version. The resulting program completed the task in just about one month. However, my boss was afraid that when the datastore would grow a bit more, we would again be in trouble. That's when he asked me to look it over. I started by investigating the problem, which at first glance looked like a network traversing problem. I soon realised it could be solved by a nested matrix multiplication (which is, of course, a standard way to discover paths in a network). It was a matrix with about a million rows and columns, but since it contained only zeroes and ones (with a couple of thousands times more zeroes than ones), the multiplication was easy to implement in a fast way. Within half-a-day, I had built a prototype program in a high-level language which did the whole job in a few hours.

      While I am still pleased with this result, I really think it came off so well not because I was so smart, but because the assembly programmer was not really worthy of the name. Still, I often use this as an illustration for students who are writing illegible code and argue that it is so very fast.

    5. Re:Algorithms, Not Stupid Processor Tricks by dragons_flight · · Score: 2, Interesting

      As someone that probably operates in the world of the other 1% (academic progammer with computational tasks measured in hours, days, or even weeks), I can still say that it is almost always about the algorithm.

      Every once in a while it really is worth careful instruction level optimization when you have a loop that must execute more than 100 million times, or some such. But the biggest gains in computational speed are always about figuring out the best approach to a problem.

    6. Re:Algorithms, Not Stupid Processor Tricks by lgw · · Score: 2, Insightful
      The places code most needs optimizaion are unlikely to be helped by the compiler anyway:
      • Unnecessary use of malloc/new instead of just using the stack
      • Unnecessary disk I/O
      • Not considering on which side of the network a calculation should be performed
      There are a few places where algorithmic optimization can help, but geenrally only with very new programmers. Far more often, it's the unintended and quite expensive consequences of library calls that cause much performance greif.
      --
      Socialism: a lie told by totalitarians and believed by fools.
    7. Re:Algorithms, Not Stupid Processor Tricks by beelsebob · · Score: 4, Informative
      That's not really the point being made though - the question really is "is it worth spending the next week trying to make optimisations, or coding a better algorithm to do this."

      And while we're at it - n^2 vs 2^n *is* a big deal when working on 1ghz+ systems... If we have 1000 objects, an operation that takes 10 cycles and an n^2 algorithm, then we get a runtime of 0.01 seconds (10 x 1000 x 1000 cycles ), if we have a 2^n algorithm then we get a runtime in the hours, and no amount of optimizing the code in the loop (even down to one instruction) is going to get us anywhere near the n^2 algorithm.

    8. Re:Algorithms, Not Stupid Processor Tricks by doktor-hladnjak · · Score: 2, Insightful

      Heap sort can be worth it if you don't need all of the elements to be sorted. For example, say you wanted only the smallest 1% of elements from an array sorted.

      A heap can be constructed in linear time, but extracting each next smallest element takes log time. Hence, getting the m smallest/largest elements out of an array of n elements takes O(n + m log n). If m is small, we're talking linear sorting time wrt to the total size overall. If n = m, the whole thing becomes O(n log n), which is the provably lowest bound on sorting any ordered sequence. However, in practice the heap overhead usually makes something like quicksort faster in such cases where m is close to n.

      A classical example of where you might use this is Kruskal's minimum spanning tree algorithm. For a large graph, typically only a smallish fraction of the edges is ever needed. With heap sort, you avoid having to fully sort all the edges by weight.

    9. Re: Algorithms, Not Stupid Processor Tricks by gidds · · Score: 2, Insightful
      The knack is knowing when to go for something flash, and when to use something simple, even if it theoretically performs worse.

      And that knack is called profiling.

      It doesn't need to be anything fancy, or use flash tools -- in fact, when it's most needed, the best method is counting seconds in your head!

      For example, an application I've worked on recently started with a bubble sort, which was taking the best part of a minute to run (handheld machine). We tried a quicksort, but the slowness of recursion in this language made hardly any faster. So I ended up with a combsort, which is a bubble sort variation -- much simpler than the quicksort, and with a higher big-O order, but the much lower overhead made it run in a fraction of the time. It was nowhere near as flash, but it was a better choice for the app.

      The important points here are a) I wouldn't have realised how inappropriate quicksort was if I hadn't compared it, and b) an advanced algorithm can run slower than a simpler one, especially with small numbers or bad language support). Don't rely on preconceptions.

      --

      Ceterum censeo subscriptionem esse delendam.

  6. Clear & Concise Code by kwiqsilver · · Score: 4, Interesting

    It's better to write clear, legible code that saves a human minutes of reading, than complex code that might save a computer a few milliseconds of processing time per year, because human time costs more than machine time.
    Also the clear code will result in fewer misinterpretations, which will mean fewer bugs (especially when the original author is not the one doing maintenance years later), further reducing costs in dollars, man hours, and frustration.

  7. NULL not always 0 by leomekenkamp · · Score: 2, Insightful

    Aren't there machines out there where the C compiler specifically defines NULL as value that is not equal to 0? I recall reading that somewhere, and that was my reason for using ==NULL instead of !. My C days are long gone though...

    --
    Wenn ist das Nunstueck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.
    1. Re:NULL not always 0 by HeghmoH · · Score: 3, Informative

      NULL isn't necessarily equal to 0 at the machine level. However, at the language level, 0 is always interpreted exactly the same as NULL if it's being converted to a pointer, and vice versa. This is explicitly spelled out in the C standard, so any compiler that doesn't obey this is breaking the standard. Saying !ptr and ptr == NULL is always identical on a conforming compiler (which they pretty much all are).

      --
      Mod down posts with a "Free Mac Mini/iPod" sig, they're spam!
    2. Re:NULL not always 0 by LiquidCoooled · · Score: 2, Informative

      Your right about none zero memory pointers (I was just re-reading a FAQ compiled from the K&R bible).

      BUT as part of an C compiler, using a "0" in a pointer context will always compile to a null pointer on the target system.

      The only problems with zeros comes from the cast applied when passing parameters, and in such cases, even a NULL definition may require explicit casting.

      --
      liqbase :: faster than paper
    3. Re:NULL not always 0 by Malc · · Score: 2, Informative

      Maybe you've been listening to C++ people? Stroustrup certainly has a chip on his shoulder about NULL:

      5.1.1 Zero

      Zero (0) is an int. Because of standard conversions, 0 can be used as a constant of an integral, floating-point, pointer, or pointer-to-member type. The type of zero will be determined by context. Zero will typically (but not necessarily) be represented by the bit pattern all-zeros of the appropriate size.

      No object is allocated with the address 0. Consequently, 0 acts as a pointer literal, indicating that a pointer doesn't refer to an object.

      In C, it has been popular to define a macro NULL to represent the zero pointer. Because of C++'s tighter type checking, the use of plain 0, rather than any suggested NULL macro, leads to fewer problems. If you feel you must define NULL, use

      const int NULL = 0;

      The const qualifier prevents accidental redefinition of NULL and ensures that NULL can be used where a constant is required.

  8. Code Twiddling by bsd4me · · Score: 2, Informative

    There really is no one answer to this, as it depends on the compiler itself, and the target architecture. The only real way to be sure is to profile the code, and to study assembler output. Even then, modern CPUs are really complicated due to pipelining, multilevel cache, multiple execution units, etc. I try not to worry about micro-twiddling, and work on optimizations at a higher-level.

    --

    (S(SKK)(SKK))(S(SKK)(SKK))

  9. From the "Patenting Fire" department by slipnslidemaster · · Score: 4, Funny

    I just checked the U.S. Patent office and sure enough, just minutes after your post, Microsoft patented "if (!ptr)" as a shorthand for "if (ptr==NULL)".

    Prepare to be sued.

    --


    "What the hell is an aluminum falcon?"
  10. Tradeoffs by Black+Parrot · · Score: 4, Insightful


    Hard to measure, but what is the tradeoff between increased speed and increased readability (which is a prerequisite for correctness and maintainability)? And if you can estimate that tradeoff, which is more important to the goals of your application?

    As a side note, it is far more important to make sure you are using efficient algorithms and data structures than to make minor local optimizations. I've seen programmers use bizarre local optimization tricks in a module that ran in exponential time rather than log time.

    --
    Sheesh, evil *and* a jerk. -- Jade
  11. Re:Bad example by hpa · · Score: 2, Insightful

    Bullshit.

    Read the C standard about the definition of a null pointer constant.

  12. Optimize at the interpreter/compiler level... by sporty · · Score: 2, Interesting

    Common idioms should be compiled away, like !x or x!=0. Uncommon idioms can't and probably shouldn't be attempted, i.e. if(!(x-x)) (which is always false). Ask your compiler maker and see if patches can be made for these types of things. 'cause if you think to do it one way, chances are, many others may try it too. It would be for their benefit to make a better compiler.

    --

    -
    ping -f 255.255.255.255 # if only

  13. Most people should not bother by El+Cubano · · Score: 5, Insightful

    What about code that is more complex? Now that compilers have matured over years and have had many improvements, I ask the Slashdot crowd, what they believe the compiler can be trusted to optimize and what must be hand optimized?

    Programmers cost lots more per hour than computer time. Let the compiler optimize and let the programmers concentrated on developing solid maintainable code.

    If you make code too clever in an effort to try to pre-optimize, you end up with code that other people have difficulty understanding. This is leads to lower quality code as it evolves if the people that follow you are not as savvy.

    Not only that, but the vast majority of code written today is UI-centric or I/O bound. If you want real optimization, design a harddrive/controller combo that gets you 1 GBps off the physical platter (and at a price that consumers can afford).

  14. The most important optimization... by slavemowgli · · Score: 2, Insightful

    The most important optimization is still the optimization of the algorithms you use. Unless under the most extreme circumstances, it doesn't really matter anymore whether the compiler might generate code that takes two cycles more than the optimal solution on today's CPUs; instead of attempting to work around the compiler's perceived (or maybe real) weaknesses, it's probably much better to review your code on a semantic level and see if you can speed things up by doing them differently.

    The only exception I can think of is when you're doing standard stuff where the best (general) solution is well-known, like sorting; however, in those cases, you shouldn't reinvent the wheel, anyway, but instead use a (presumably already highly-optimized) library.

    --
    quidquid latine dictum sit altum videtur.
  15. Beware of habits. by SharpFang · · Score: 4, Interesting

    I got in the habit of writing "readable but inefficient" code, taking care that my constructs don't get too sophisticated for the optimizer but then depending on gcc -O3 thoroughly. And then it happened I had to program 8051 clone. Then I learned there are no optimizing compilers for '51, that I'm really tight on CPU cycles, and that I simply don't know HOW to write really efficient C code.
    Ended up writing my programs in assembler...

    --
    45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B2
    1. Re:Beware of habits. by Felonious+Monk · · Score: 2, Insightful

      A good point, but code for embedded devices, or any code that has to interface with real-time physical processes, is really a different ball game.

  16. Huh by NullProg · · Score: 4, Informative


    As a simple example, take 'if (!ptr)' instead of 'if (ptr==NULL)'.


    Both forms resolve to the same opcode. Even under my 6502 compiler.


    CMP register,val
    JNE


    Enjoy,

    --
    It's just the normal noises in here.
    1. Re:Huh by DunbarTheInept · · Score: 4, Insightful

      Not true. Many CPUs have a unary jump-if-zero, or a jump-if-nonzero operation. Thus the comparasin step can be bypassed since you know you're comparing to zero.

      However, any compiler worth anything should find that and optimize it very easily in the case where you're comparing to a constant that evaluates to zero.

      --

      Don't label something "offtopic" unless you know the topic well enough to tell what's on topic.

    2. Re:Huh by gatkinso · · Score: 2, Informative

      Sort of correct.

      According to the language definition, a constant 0 in a pointer context is converted into a null pointer at compile time. That is, in an initialization, assignment, or comparison when one side is a variable or expression of pointer type, the compiler can tell that a constant 0 on the other side requests a null pointer, and generate the correctly-typed null pointer value.

      Check out section 5.2

      http://www.faqs.org/faqs/C-faq/faq/

      --
      I am very small, utmostly microscopic.
    3. Re:Huh by PitaBred · · Score: 2, Informative

      As people said above, the language definition dictates that 0 == NULL. Mod parent idiot.

  17. $.02 by MagicM · · Score: 4, Insightful

    1) Code for maintainability
    2) Profile your code
    3) Optimize the bottlenecks

    That said, (!ptr) should be just as maintanable as (ptr == NULL) simply because it is a frequently used 'dialect'. As long as these 'shortcuts' are used throughout the entire codebase they should be familiar enough that they don't get in the way of maintainability.

  18. Tight complex recursive loops by LiquidCoooled · · Score: 2, Interesting

    An example would be searching and sorting algorythms (I know there have been thousands of variations, and entire libraries now exist, but theres always some other need for a non generic search function)

    I could write sloppy code which appears to be significant, but then realise that holding this here, and keeping that register there, then I can do such a thing just a fraction quicker than before.

    Its not so much going to the assembler level anymore, but a tightly coded loop tuned by human intuition will almost always still be faster than anything an optimiser can give.

    I recently had an issue with sorting collections containing thousands of none trivial objects. Every time I adjusted the adready fast quicksort, I gained a little more speed.

    Its always been the way, and until genetic compilation and optimisation comes along trying every combination, it will continue to be the case.

    --
    liqbase :: faster than paper
  19. micro optimization by fred+fleenblat · · Score: 4, Insightful

    What you're talking about it micro-optimization.
    Compilers are pretty good at that, and you should let them do their job.

    Programmers should optimize at a higher level: by their choice of algorithms, organizing the program so that memory access is cache-friendly, making sure various objects don't get destroyed and re-created unnecessarily, that sort of thing.

  20. Wrong, wrong, wrong by JoeBuck · · Score: 4, Informative
    Don't give advice when you don't know C. C requires that when a 0 is converted to a pointer, the result is NULL, so it is absolutely false to claim that NULL could be defined as -1.

    "ptr == 0" must give the same result as "ptr == NULL", always.

    1. Re:Wrong, wrong, wrong by Anonymous Coward · · Score: 4, Informative

      From the ANSI C specification, section 6.2.2.3:

      An integral constant expression with the value 0, or such an expression cast to TypeIs_VoidPointer, is called a null pointer constant. If a null pointer constant is assigned to or compared for equality to a pointer, the constant is converted to a pointer of that type. Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. A null pointer constant has TypeIs_NULL.

      Once again, it should be said:

      Don't give advice not to give advice to not give advice when you don't know C when you don't know C when you don't know C.

    2. Re:Wrong, wrong, wrong by swillden · · Score: 3, Informative

      Althoug the comparision (0 == ptr) might for some twisted reason com out as a non-zero value, you are not guaranteed that (!ptr) will have the same value.

      Wrong

      Don't give advice... ah, screw it. You get the idea.

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    3. Re:Wrong, wrong, wrong by PoopJuggler · · Score: 3, Interesting

      Any company who makes a C compiler where NULL != 0 will not get much business methinks

    4. Re:Wrong, wrong, wrong by wiredlogic · · Score: 2, Interesting

      No, "implementation defined" means that it is up to the compiler, OS (if present), and possibly the hardware to determine what will be used to represent the NULL address.

      This is addressed in the C-FAQ where systems from Prime, Data General, and Honeywell-Bull are noted for having non-zero null pointers (at least for their C-compilers).

      This issue brings up one of my pet peeves with C++. The designers (I don't think Stroustroup deserves all the blame)went all out in adding weak type safety to the language by eliminating automatic casts but then they determined that "((void)(*0))" violated they safety model and decided to invoke special "spooky" behavior when comparing pointers against the literal zero. This of course leads to the annoying practice of leaving out the Boolean operator altogether and using "if(foo)" and "if(!foo)".

      I imagine the C++ architects were at least partially motivated by their "macros are evil" mantra (why they didn't do anything about the need for header guard macros is beyond me). They should have had the guts to introduce a new "null" keyword. This would not conflict with existing ANSI C code using NULL and code could easily be ported with substitution or:

      #define NULL null
      I can't believe that this wasn't proposed at some time. It must have been shot down because someone complained that it would break their legacy C code. Only a fool would put case variants of standard macros and keywords into their C code and porting older pre-standard-NULL K&R code would require revisions anyway. They deserve any breakage if they tried to port such crap to C++.
      --
      I am becoming gerund, destroyer of verbs.
  21. Those who forget Tony Hoare... by smug_lisp_weenie · · Score: 5, Insightful

    ...are doomed to repeat the biggest trap in computer programming over and over again:

    "Premature optimization is the root of all evil"

    If there's only one rule in computer programming a person ever learns, "Hoare's dictum" is the one I would choose.

    Almost all modern languages have extensive libraries available to handle common programming tasks and can handle the vast majority of optimizations you speak of automatically. This means that 99.99% of the time you shouldn't be thinking about optimizations at all. Unless you're John Carmack or you're writing a new compiler from scratch (and perhaps you are) or involved in a handful of other activities you're making a big big mistake if your spending any time worrying about these things. There are far more important things to worry about, such as writing code that can be understood by others, can easily be units tested, etc.

    A few years ago I used to write C/C++/asm code extensively and used to be obsessed with performance and optimization. Then, one day, I had an epiphany and started writing code that is about 10 times slower than my old code (different in computer language and style) and infinitely easier to understand and expand. The only time I optimize now is at the very very end of development when I have solid profiler results from the final product that show noticable delays for the end user and this only happens rarely.

    Of course, this is just my own personal experience and others may see things differently.

    1. Re:Those who forget Tony Hoare... by neonstz · · Score: 3, Insightful
      A few years ago I used to write C/C++/asm code extensively and used to be obsessed with performance and optimization. Then, one day, I had an epiphany and started writing code that is about 10 times slower than my old code (different in computer language and style) and infinitely easier to understand and expand. The only time I optimize now is at the very very end of development when I have solid profiler results from the final product that show noticable delays for the end user and this only happens rarely.

      It is important to be aware of that here are different types of optimizing. Optimizing code where the compiler probably does a good job is just stupid unless the code turns out to be a major bottleneck.

      However, not thinking about optimization/speed early can IMHO be very dangerous. If the project is a bit large and complex, a nice design on the whiteboard may very well turn up to be dead slow with no chance in hell to make it run significantly faster without redesigning/rewriting the entire thing (this doesn't really have anything to do with compiler optimization though).

      I've been working in a project (I wasn't in it in the beginning), where the design probably looked good for some people in the design document (although I don't really agree on that neither), but the performance aspect was neglected until the application turned out to be quite slow. Adding mechanisms to make it run faster has been quite "challenging". (My personal opinion in this piece of software is that performace issues was ignored even from early design because the wrong people making the decisions. Basically they didn't focus on where performance really was needed.

      So after a few years my experience bottles down to: "If you have a performace requirement, make sure your code keeps up the entire time." and "You can't get both high performance and general purpose stuff in the same piece of code".

  22. Write C for C programmers by swillden · · Score: 5, Insightful

    With regard to your example, I can't imagine any modern compiler wouldn't treat the two as equivalent.

    However, in your example, I actually prefer "if (!ptr)" to "if (ptr == NULL)", for two reasons. First the latter is more error-prone, because you can accidentally end up with "if (ptr = NULL)". One common solution to avoid that problem is to write "if (NULL == ptr)", but that just doesn't read well to me. Another is to turn on warnings, and let your compiler point out code like that -- but that assumes a decent compiler.

    The second, and more important, reason is that to anyone who's been writing C for a while, the compact representation is actually clearer because it's an instantly-recognizable idiom. To me, parsing the "ptr == NULL" format requires a few microseconds of thought to figure out what you're doing. "!ptr" requires none. There are a number of common idioms in C that are strange-looking at first, but soon become just another part of your programming vocabulary. IMO, if you're writing code in a given language, you should write it in the style that is most comfortable to other programmers in that language. I think proper use of idiomatic expressions *enhances* maintainability. Don't try to write Pascal in C, or Java in C++, or COBOL in, well, anything, but that's a separate issue :-)

    Oh, and my answer to your more general question about whether or not you should try to write code that is easy for the compiler... no. Don't do that. Write code that is clear and readable to programmers and let the compiler do what it does. If profiling shows that a particular piece of code is too slow, then figure out how to optimize it, whether by tailoring the code, dropping down to assembler, or whatever. But not before.

    --
    Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    1. Re:Write C for C programmers by Anonymous Coward · · Score: 2, Funny

      And write C++ for C++ programmers:

      try
      {
      if (1 / (int)ptr)
      ;
      cout << "ptr is not null";
      }
      catch (...)
      {
      cout << "ptr is null";
      }

    2. Re:Write C for C programmers by 14erCleaner · · Score: 3, Interesting
      I disagree with you about the readability of (!ptr), but at least it is a very common idiom in C, and I can accept that.

      But please, oh, please, don't write this:

      if (!strcmp(x,y))

      Intuitively, that looks exactly backwards from what it's testing (equality).

      On the "optimize for the compiler" issue, I think what's been said already is right: don't do it unless it's in a critical spot, write code for readability (and big-picture efficiency) first, then worry about local optimizations only if there's a problem.

      --
      Have you read my blog lately?
    3. Re:Write C for C programmers by syukton · · Score: 2, Funny

      I've always had a problem with that whole !strcmp(x,y) thing.

      So I made a macro called STRCMP which can be used in a manner which reads better logically. ;)

      --
      Reinvent the wheel only at either a lower cost, greater effectiveness, or your own personal enrichment and satisfaction.
  23. code should be written for people to read by SamSeaborn · · Score: 5, Insightful

    "Programs should be written for people to read, and only incidentally for machines to execute."
    - Structure and Interpretation of Computer Programs

  24. Not a question that can be asked generally by Sycraft-fu · · Score: 4, Informative

    Each compiler is different. Some will optimise things other won't.

    In general, however, systems are now fast enought that when in doubt, write the clearest code possible. I mean for most apps, speed is not critical, however for all apps stability and lack of bugs is important and obscure code leads to problems.

    Also, for things that are time critical, it's generall just one or two little parts that make all the difference. You only need to worry about optimizing those inner loops where all the time is spent. Use a profiler, since programmers generally suck at identifying what needs optimising.

    Keep it easy to read and maintain, unless speed is critical in a certian part. Then you can go nuts on hand optimization, but document it well.

  25. Check out the LLVM demo page by sabre · · Score: 5, Interesting

    LLVM is an aggressive compiler that is able to do many cool things. Best yet, it has a demo page here: http://llvm.org/demo, where you can try two different things and see how they compile.

    One of the nice things about this is that the code is printed in a simple abstract assembly language that is easy to read and understand.

    The compiler itself is very cool too btw, check it out. :)

    -Chris

  26. Re:write clearer code first by hpa · · Score: 2, Informative
    The former is a lot more concise, and conciseness helps getting the *big* concepts down.

    Anyone with any familiarity with C will consider the latter form unnecessarily more verbose, and therefore less clear.

    There is one exception to that, and that is when "ptr" is in fact a complex expression that it isn't obvious at a glance is a pointer expression. In that case, == NULL or != NULL spells out to the reader of the code "oh, and by the way, it's a pointer." That is the ONLY reason to write this for clarity.

    There is a whole category of "bad commenting" in which comments left that are only useful to someone who don't know the programming language actually makes the code a lot harder to read. A comment like:

    a += 2; /* Add two to a */

    ... is not helpful in any shape, way or form, and just provides mental clutter.

  27. That's a Tony Hoare quote, not Donalded Knuth by Dan+Ost · · Score: 4, Informative

    Donald Knuth was quoating Tony Hoare when he said that.

    --

    *sigh* back to work...
  28. use a good profiler!! by EccentricAnomaly · · Score: 2, Informative

    Trying to optimize in your head rarely does any good... Use a good profiling tool (like Apple's Shark) to find out what part of your code uses the most time and then just concentrate on making that part faster.

    Using a profiler and your own brain you can often significantly improve over what a compiler can do.

    --
    There are 10 types of people in this world, those who can count in binary and those who can't.
  29. "if (0 != variable)" is for wimps by zapatero · · Score: 2, Interesting


    Those that advocate the constant first in if boolean comparisons are the feeble minded who believe ever bit of propaganda and PC reporting they read.

    It's especially annoying to see it done in programming languages like Java where assignments are not even allowed in if statements. When I see java code like this:
    if (0 == x)
    I'm thinking "loser".

    Back to C. And besides gcc since C-99 has issued warnings for assignments in the "if" expression when not embedded in parenthesis.
    example...
    if (x = 3) ... will result in a warning.
    if ((x = 3)) ... no warning.

  30. Re:Neither are correct. by HeghmoH · · Score: 2, Insightful

    Putting the value on the left side prevents == VS = mixups

    So does using -W -Wall -Werror, and that lets you write your statements naturally and protects you when comparing two variables.

    Relying on NULL #define-ition to be compatible with all pointer types is risky.

    Relying on behavior that is explicitly specified in the ISO/ANSI standard is never risky.

    --
    Mod down posts with a "Free Mac Mini/iPod" sig, they're spam!
  31. Stupid question by PrismaticBooger · · Score: 2, Insightful
    I have been coding in C for a while (10 yrs or so) and tend to use short code snippets. As a simple example, take 'if (!ptr)' instead of 'if (ptr==NULL)'. The reason someone might use the former code snippet is because they believe it would result in smaller machine code if the compiler does not do optimizations or is not smart enough to optimize the particular code snippet.
    That's simply inane. Why don't you check the assembly your compiler generates? If your're really up for shits and giggles, compare it to a C compiler from 10 years ago.
    IMHO the latter code snippet is clearer than the former, and I would use it in my code if I know for sure that the compiler will optimize it and produce machine code equivalent to the former code snippet.
    So why are you asking here? Check what your compiler generates. Incidentally, I find the former more readable. While you might be under the illusion that people do use it as an optimization technique, many simply find it easier to read and write. It's a widely accepted and understood idiom for checking pointer validity. And in C++, it has the benefit of being able to look the same whether ptr is a smart pointer or a raw pointer.
    The previous example was easy. What about code that is more complex? Now that compilers have matured over years and have had many improvements, I ask the Slashdot crowd, what they believe the compiler can be trusted to optimize and what must be hand optimized?
    Write readable code. Ask a profiler what you need to optimize.
  32. Only hand optimize what matters by HalWasRight · · Score: 2, Insightful
    • "Premature optimization is the root of all evil" -- C.A.R. Hoare

      "This mission is too important to allow you to jeopardize it." -- HAL

    Seriously, why would you waste your time obfuscating your code when you don't have too? Unless you know through profiling that detailed statement level code is bad then you are shooting yourself in the foot.

    This isn't to say that when making architecture level decisions that you shouldn't optimize. O(N^2) is bad, Um'Kay? O(N) is alright for small N, but O(log N) is better when you know you'll have a significant N. That's the stuff a compiler can't do for you today.

    Once you've profiled, and you know something is critical and can be done better and matters, then start obfuscating. There is a lot you can do in C to optimize, especially with DSP codes, so resorting to ASM should only be done for the most extreme cases.

    --
    "This mission is too important to allow you to jeopardize it." -- HAL
  33. Re:Neither are correct. by hpa · · Score: 2, Interesting

    if (0!=ptr) is a hideous abortion, because it's not readable.

    Also, your statement that "relying on NULL to be compatible with all pointer types is risky" is just plain wrong.

  34. Devise an appropriate test by Medievalist · · Score: 2, Informative


    Back when I was doing real-time programming in FORTRAN-II on a PDP-11/34, I was able to very slightly decrease execution time by changing "divide by two" instructions to arithmatic shifts and "square root" operations to "power of 1/2" (because x^.5 = sqrt(x)).

    Since those instructions were in a loop that was running 80,000 times per second, this meant that I could get more data when destructively testing rocket motors... in the end, I got a 40% increase in processing speed that was worth a whole lot of money to the company. AND it got me a raise ;) so don't tell ME little increases in efficiency aren't worthwhile!

    The answer to your question is TEST your unique combination of hardware and software, find out what works better/faster/more-elegantly, and use the most human-readable form that you can afford to given your unique requirements.

    If you are doing real-time digital data acquisition involving usecond events, you will probably end up with some pretty cryptic source code, so be nice and put in lots of comments.

    If you are programming an office automation application, your code should probably be readable by kindergarteners, since you won't have very difficult performance requirements.

  35. Re:You're asking the wrong crowd by LakeSolon · · Score: 2, Insightful

    You do realize slashdot is written in perl, yes? Or have you not noticed the contents of the URL, your own comment for example http://ask.slashdot.org/comments.pl?sid=140256&cid =11781397

    ~Lake

  36. Re:Neither are correct. by Cthefuture · · Score: 2, Insightful

    I have seen this syntax used sometimes. Personally, I find it difficult to read. The problem is that you have reversed the logic in a LISP-like way. There is a reason LISP is not mainstream, think about it.

    IMHO, a good programming language is an extension of your thought processes. No current language is particularly great, but some are better than others because they work more like the way we think. This is a huge part of Object-Oriented programming, its purpose is mostly grouping and categorizing things. That's what humans do, group and catagorize. Note that I'm not saying OOP is the answer to everything, I believe all programming idioms have there place. However, there are good reasons why OOP got popular.

    When I'm working with a particular variable, in my head I'm thinking "I need to check this variable against NULL" (ie. variable == NULL). I absolutely do not think "NULL, what kinds of things are NULL." That would be backwards.

    Anyway, back to the optimization thing. I use things like if (!ptr) all the time but not for optimization purposes. People use that test so often that I don't think anyone thinks it's confusing. Sometimes I will use the more verbose test if the code is particularly complex but the thought of it being less optimal never entered my mind because even if it were slower, it would be such a small difference that it wouldn't matter.

    Too often I see people "optimizing" code that doesn't need to be optimized due to the fact that there are other places in the code that are much, much slower making the optimization such a small benefit that there is no reason to do it in the first place.

    On the other side of that, I see people ignoring optimization thinking that if they need to make it faster they can worry about that later. Then after 10,000 lines of code they realize that the system is too slow and there is nothing they can do about it because of bad (slow) design decisions made throughout the process.

    --
    The ratio of people to cake is too big
  37. Language paradigms by alexo · · Score: 2, Insightful

    > I have been coding in C for a while (10 yrs or so) and tend to use short code snippets.
    > As a simple example, take 'if (!ptr)' instead of 'if (ptr==NULL)'.
    > The reason someone might use the former code snippet is because they believe it would result
    > in smaller machine code if the compiler does not do optimizations or is not smart enough
    > to optimize the particular code snippet.


    No programmer believes that.
    In C, NULL is #define-ed to 0 and the "!" operator also compares against zero so every compiler should generate exactly the same code for both.

    > IMHO the latter code snippet is clearer than the former, and I would use it in my code

    Actually I prefer to write (and read) the former and I do find it clearer, mostly because it is idiomatic in C et al.

    Another good reason is that the former works better in C++ because it enables you to substitute "smart" objects for plain pointers and use them in a more natureal way (especially in templates).

    (Aside: most platforms that have C compilers also have deccent C++ compilers)

    > if I know for sure that the compiler will optimize it and produce machine code equivalent to the former code snippet.

    See above. There is nothing to optimize.

  38. The algorithm that must not be named! by coyote-san · · Score: 4, Funny

    Grrr, you named the algorithm that must not be named! Cursed be the name of the fool who thought it would be a good algorithm for introductory students - I've lost count of the number of people convinced that this satan-spawned algorithm is faster than an insertion sort (it's not) and that there's no reason for them to learn to use the qsort() function. N.B., not to implement a quick sort, but to simply call a standard library routine.

    The most frustrating thing is that, if you must use the algorithm that must not be named, the bidirectional form of the algorithm is much faster (in practice) than the unidirectional form yet really no more complex to code than the latter if you have any potential as a software developer.

    --
    For every complex problem there is an answer that is clear, simple, and wrong. -- H L Mencken
    1. Re:The algorithm that must not be named! by GMontag451 · · Score: 3, Funny
      Hehe. Heard about bogosort? Use random permutations and check if you have the data sorted.

      The many-worlds version of bogosort is the fastest possible sorting algorithm though. Its O(C). For those that don't know, the many-worlds version just does one random permutation, with a new universe being created for each possible outcome of the permutation. You then destroy all the universes were the dataset isn't sorted.

    2. Re:The algorithm that must not be named! by aixou · · Score: 2, Insightful

      Why not stick with insertion then? It has a run time of n on perfectly sorted data...

    3. Re:The algorithm that must not be named! by TheLink · · Score: 2, Funny

      Shoot the programmer who uses bogosort.

      The programmer will be alive in the universes which bogosort worked well.

      --
  39. IBM says let the compiler optimize by opticsguy · · Score: 2, Informative

    I recently attended a code optimization workshop for the IBM PPC compiler for Mac OSX. The compiler designer stressed that hand optimized code (i.e. unrolled loops, register variables, stupid pointer tricks etc.) only confused the optimizing compiler and would usually result in slower code overall when -O4 and higher optimizations are enabled. He provided a number of examples why this was the case and convinced us that modern compilers are much better at optimizing than humans. He also stressed the need to profile code and look for things the compiler cannot optimize. Examples are using double floats where single precision will suffice and in the case of the PPC unecessary conversions between floats and integers.

  40. Never trust a complier by papaver1 · · Score: 2, Informative

    I took a compliers class a year or so ago. We had to make a complier in c using lex/yacc for pascal. We also put in some optimization in it. But or profressor who has been doing this for around 10 years or so alwasy said to never trust a complier for optimizing your code. most don't do a very good job of it. and each complier optimizes stuff diffrently. some even broke code. His comparisons were using gcc, ibm complier, and a couple others, as well as optimizing in the code itself. The optimized code ran better in 90% of the runs.

  41. That's not as funny as you think by Chemisor · · Score: 2, Insightful

    > Every programmer worth his/her salt knows that
    > source code is self documenting...

    And it's true too. Although comments are indeed a good thing, writing code that does not require them is a much better one. If your code needs comments, it's probably too complex for continued maintenance.

    1. Re:That's not as funny as you think by rleibman · · Score: 2, Interesting

      Of course, the knife cuts both ways. If you comment everything and then the logic changes during maintenance without a corresponding change to the comments, they becomse worse than convoluted code (at least convoluted code can run through a debugger to give you an idea of what's happening).
      That would then be because your commented the wrong thing. Comments should have nothing to say on what is being done, that should be obvious by the code, comments have much more value, become obsolete less often and make code cleaner when they explain why things are done: comments give the big picture, the code the details. Steve McConnel's "Code Complete" is a wonderful treatise on this and other good things.
      As a trivial example:
      int a = b + 1; //Make a equal b plus one That's clearly stupid, but it's surprising how often I see code like this.

  42. Re:Not Machine Performance but Programmer Performa by soft_guy · · Score: 2, Insightful

    Bullshit. Some basic checks on performance are always appropriate as part of your debugging. For example, on MacOS X, I recommend you at least do two things in your app:

    1. Run top and look at the amount of CPU usage your app has during different parts of its operation. It should not, for example, run at 99% CPU usage while idle.
    2. Run QuartzDebug to make sure you aren't doing gratuituous amounts of extra drawing. Examples: redrawing more often than necessary, redrawing more area than necessary.

    And yes, for the average application, I still care about these things.

    If certain operations seem to be slow, run an optimization tool and see what "low hanging fruit" you can address.

    I've worked on several professional applications and while some of them are "weird", some level of optimization has always been important.

    --
    Avoid Missing Ball for High Score
  43. ANSI C by bAdministrator · · Score: 2, Informative

    ANSI C: "The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant."

    The definition of a null pointer constant: "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant."

    Source: Programming languages - C (ISO/IEC 9899:1999)
  44. Re:write clearer code first by DunbarTheInept · · Score: 2, Insightful

    I agree that you should write the more clear form, and damn the optimization. But I disagree that the second form is the more clear one. The first one reads as "if not pointer", which very consisely and completely conveys the meaning that is intended, which is "If this thing isn't really a pointer to anything."

    The problem comes from the fact that some functions that return integers do so in a way that has the inverse of the intuitive boolean interpretation. (Zero means true). One example is strcmp(), I'd much rather see if( strcmp(s1,s2) == 0 ) than if( ! strcmp(s1,s2) ), since the boolean version has 100% inverted meaning from what it looks like. System calls (man page 2) typically have the same problem. It's not that the calls themselves are bad (they have good reasons to return zero for success - becuase they have more than one kind of failure), but that the people using them should never have gotten into the habit of using inverted boolean symbology to interpret them in their code.

    If an integer doesn't behave like a boolean, then just treat it as an integer. Don't take advantage of the lose typing of C to treat it like a boolean that means the opposite of what it means.

    --

    Don't label something "offtopic" unless you know the topic well enough to tell what's on topic.

  45. If you're not willing to TIME it... by dpbsmith · · Score: 4, Insightful

    ...then the code isn't important enough to optimize. Plain and simple.

    Never try to optimize anything unless you have measured the speed of the code before optimizing and have measured it again after optimizing.

    Optimized code is almost always harder to understand, contains more possible code paths, and more likely to contain bugs than the most straightforward code. It's only worth it if it's really faster...

    And you simply cannot tell whether it's faster unless you actually time it. It's absolutely mindboggling how often a change you are certain will speed up the code has no effect, or a truly negligible effect, or slows it down.

    This has always been true. In these days of heavily optimized compilers and complex CPUs that are doing branch prediction and God knows what all, it is truer than ever. You cannot tell whether code is fast just by glancing at it. Well, maybe there are processor gurus who can accurately visualize the exact flow of all the bits through the pipeline, but I'm certainly not one of them.

    A corollary is that since the optimized code is almost always trickier, harder to understand, and often contains more logic paths than the most straightforward code, you shouldn't optimize unless you are committed to spending the time to write a careful unit-test fixture that exercises everything tricky you've done, and write good comments in the code.

    1. Re:If you're not willing to TIME it... by mystran · · Score: 2, Interesting
      Actually, while I agree on the main point, I must disagree to a certain degree, because my empirical experience suggests something different: If something looks complicated, there's a good chance that by trying to write it in a more clear/straightforward (so as to make it easier to understand) will also result in more efficient machine code (as benchmarked).

      As such, I'd say: if something is too slow, benchmark it, then try to write a more simple version and benchmark that. Many times the result will be faster (and rest of the time you probably need a better algorithm).

      As funny as it sounds, because compilers do fancy optimizations, writing code to "explain the logic to the compiler" might well enable optimizations that a compiler couldn't use on "more optimized" code. One obvious (and simple) example is the "const"-modifier in C, which helps clarify extent of usage to both other programmers AND the compiler; the result in performance can be quite dramatic in truly CPU-bound code.

      --
      Software should be free as in speech, but if we also get some free beer, all the better.
  46. My experience by pclminion · · Score: 3, Insightful
    First, let me say what sort of code I write. I work almost exclusively with high-performance, 2D graphics code. Most of what I do involve manipulating bits, worrying about cache utilization, and squeezing the last bits of performance out of a three line inner loop. I'm just going to rattle off what I know from my experience with gcc and VC++:

    The compiler will perform strength reduction in all reasonable instances.
    The compiler will raise invariant computations from inner loops in almost all cases that do not involve pointers.
    The compiler knows how to optimize integer division in ways I wouldn't have even thought of.
    The compiler sometimes "forgets" about a register and produces sub-optimal code for inner loops.
    The compiler can't always tell what variable is most important to keep in a register in an inner loop.

    Other stuff:

    x^=y; y^=x; x^=y; optimizes to an XCHG instruction with gcc on x86. I was amazed that it could do that. (Yes, that piece of code exchanges x and y). On the other hand, tmp=x; x=y; y=tmp; doesn't get optimized to an XCHG. Obviously, the compiler is using a Boolean simplifier or identity-prover.

    The compiler always assumes a branch will be taken (unless you use certain compiler switches to change this behavior). Thus you should always arrange your conditional tests so that the less-often executed code is within the braces.

    Don't be afraid to write complex expressions. Subexpression elimination is almost foolproof in all instances where pointers are NOT involved. It's better to leave your code clear, and let the compiler optimize it.

    And ABOVE ALL:

    No matter how much the compiler optimizes your code, you can throw it all down the toilet with bad design by screwing the cache utilization. This is EXTREMELY important especially in graphical applications which process huge raster buffers. Row-wise processing is always more efficient than column-wise. Random access will kill your performance. Do not trust the memory allocator to keep your allocations together. Write your own allocator if you are dealing with thousands or millions of small, related chunks of information.

    I could go on... But I must also second what others have said, which is to perform algorithmic optimizations FIRST and do not bother with constant-factor optimizations until you are CERTAIN that you are using the best algorithm. If you ignore this advice you might waste a week optimizing a three-line inner loop and then come up with a better algorithm the next week which makes all your hard work redundant.

  47. Re:Indeed by Rew190 · · Score: 2, Informative

    Variables named "i" or "j" are typically used for iterating through loops. I find most programmers tend to stick to this convention, so if I'm reading through someone else's code and glance at an "i" or a "j," I know it's going to be used as a loop or iterator of some sort.

    For example, if you just saw "FIELD_COUNT" by itself without code, would you have a good idea what sort of object that was knowing anything else? (A static variable). If you saw "_count"? (Instance variable). "getCount"? (Accessor method)

    So in that sense, yes, it is meaningful. You'll pick up on things like that when you start coding larger projects with other programmers.

  48. exactly! by pyrrho · · Score: 2, Insightful

    comments can be misleading, but the code never lies, it always works exactly as written.

    --

    -pyrrho

  49. Optimization rules... by Anonymous Coward · · Score: 5, Funny

    When I wrote my ray-tracer for the final project of my graphics class, I used gcc -o3 and it optimized my code into Pov-ray, which was sweet. I was done with the project in like ten minutes.

    Plus I got extra credit for implementing phong shading. I didn't even try to do phong shading.

    1. Re:Optimization rules... by gardyloo · · Score: 3, Funny

      It's OK -- the great-grandparent poster optimized his humour code a little *too* much. Now we have to work on interpreters for /. readers...

  50. Re:Not always. by zaffir · · Score: 4, Insightful

    I make my code easy to read for my own sanity. I've lived out this bash.org quote way too many times.

    --
    "Upon attaching the waterblock to my penis, I began to notice that I know nothing about computers." -- JRockway
  51. Easy one by Anonymous Coward · · Score: 2, Informative

    $ cat one.c
    #include
    int main( int argc, char* argv[] ) {
    if( argv == NULL ) return 0; else return 1;
    }
    $ cat two.c
    #include
    int main( int argc, char* argv[] ) {
    if( !argv ) return 0; else return 1;
    }
    $ gcc -S one.c
    $ gcc -S two.c
    $ diff one.s two.s
    - .file "one.c"
    ---
    + .file "two.c"
    $ gcc -O3 -S one.c
    $ gcc -O3 -S two.c
    $ diff one.s two.s
    - .file "one.c"
    ---
    + .file "two.c"
    $ gcc --version
    gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)

    No diference at all...

  52. Re:Clear Code - Boeing by pagebt · · Score: 4, Funny

    And believe me it is a pain in the a$$. Our company did the verification for the code in the microprocessor that controls the locks to the bathroom door on a 777, if the crapper tank is full then the door locks to make sure there isn't an overflow and thus frozen turd/urine meteors that fall from the sky. Every byte of the code MUST be excercised including all error conditions.

  53. Embedded System Compilers by snipercat · · Score: 2, Insightful

    First, reading through the existing comments, the general opinion appears to be, write clear code, unless you *really* need to optimize it. Ounce for ounce I have to agree with this.

    Second, regarding the embedded system portion of the question, we have to remember that the rules for embedded systems are different than the rules for general purpose systems. Specifically, embedded systems are resource constrained and (more times than not) have real-time deadlines.

    At least so far, I have never programmed an embedded system that I needed to optomize my code for speed (best case execution time), or for space. I have needed to change an algorithm around for complexity reasons, but never for minor incremental speed improvements.

    Real time systems are more about executing on time, rather than executing fast. And yes, there is a difference. Pay close attention to your worst case execution time. If your missing deadlines occasionally, it is most likely due to unpredictable interrupts and other events in your system, not because the compiler couldn't optimize your code.

    In short, regarding any compiler/code optimization you may want to do on your embedded system, write your code first to be dependable, predictable, and on time. Worry about raw speed later.

  54. Re:Clear Code - Boeing by Anonymous Coward · · Score: 4, Funny

    So how many dumps does it take to fill up the crapper tank? I'd hate to be the last QA engineer in line to use the crapper. Also what happens when that last engineer fills up the crapper, does the bathroom door look thus trapping him inside?

  55. Premature Optimization by fizban · · Score: 4, Insightful

    Premature Optimization is the DEVIL! I repeat, it is the gosh darn DEVIL! Don't do it. Write clear code so that I don't have to spend days trying to figure out what you are trying to do.

    The biggest mistake I see in my professional (and unprofessional) life is programmers who try to optimize their code is all sorts of "733+" ways, trying to "trick" the compiler into removing 1 or 2 lines of assembly, yet completely disregard that they are using a map instead of a hash_map, or doing a linear search when they could do a binary search, or doing the same lookup multiple times, when they could do it just once. It's just silly, and goes to show that lots of programmers don't know how to optimize effectively.

    Compilers are good. They optimize code well. Don't try to help them out unless you know your code has a definite bottleneck in a tight loop that needs hand tuning. Focus on using correct algorithms and designing your code from a high level to process data efficiently. Write your code in a clear and easy to read manner, so that you or some other programmer can easily figure out what's going on a few months down the line when you need to add fixes or new functionality. These are the ways to build efficient and maintainable systems, not by writing stuff that you could enter in an obfuscated code contest.

    --

    +1 Insightful, -1 Troll. What can I say, I'm an Insightful Troll.

  56. Get your priorities straight by willow · · Score: 2, Interesting

    Most compiled programs don't need any optimization from the compiler or programmer because their performance is just not that important.

    If the program must be fast your first concern should be getting the right answer. I can make any program lightning fast as long as it doesn't have to return the right answer. This may seem trivially obvious but you'd be surprised by how many times optimization attempts end up optimizing away the right answer.

    Pick the right algorithm and implement it clearly.

    If it's too slow, break out the profiler and optimize.

    If it's still too slow, you screwed yourself by not including performance requirements at the very beginning. Maximum performance must be designed in from the start (e.g., look at high performance matrix multiply libraries)

    --
    Moderation in everything, including moderation.
  57. valgrind by cyco/mico · · Score: 4, Informative
    If in doubt, use valgrind and kcachegrind. One run with callgrind gives you all the information you want:
    • How often are functions called (and branches taken)
    • Which functions take most of the time
    • See the assembler code for each line with a mouse click (no need to guess anymore)
    callgrind/kcachegrind is by far the easiest profiling solution I ever tried, and it seems answer more or less all of your questions.
  58. i, j, k, ... by bsd4me · · Score: 4, Informative

    I think that most people forget that the reason that i, j, k, etc. are used for loop counters is that unless otherwise declared, I..N default to INTEGER in FORTRAN. This convention just carried over as programmers migrated from FORTRAN to other languages and has been passed down through the ages.

    --

    (S(SKK)(SKK))(S(SKK)(SKK))

  59. The question was full of bad examples too by einhverfr · · Score: 2, Interesting

    I would use if (!ptr) for a different reason. It is not hard to accidently type if(ptr = NULL) instead of if(ptr == NULL) thereby accidently add a reason for your program to segfault.

    If you are going to do this, it is better to do if(NULL == ptr) so that if you omit one of the equal signs, it won't compile.

    In the end we can argue these things forever. People see code differently and may find one idea elegant and easy while the other unmaintainable and unreadible. Sort of like the thread v process debate (ongoing for now what... 30 years?).

    --

    LedgerSMB: Open source Accounting/ERP
    1. Re:The question was full of bad examples too by eric76 · · Score: 3, Insightful

      I've known some very good first rate programmers who religiously put the constants on the left. I've never known a second rate programmer who did.

  60. Algorithm by mugnyte · · Score: 3, Insightful

    For a cheap, fast batch lookups I once wrote a hashed matrix using STL. Loaded all the cells, dynamically typed, added indexes on the data for that run, and then passed around this collection of in-memory tables to our routines. Ran fast and was simple to debug, since all the traversing was O(ln(n)) based (or a variant thereof). Adding serialization, we could distribute to machines overnight dynamically and cut the run to a few minutes - from almost 8 hours.

    Until it came time to dipose the memory. The STL slowly crawled tons of our objects, and the C++ dispose pattern was just too inefficient for all the stack hits. So we pointed the library at a custom heap and never disposed the dictionary - we just disposed the heap in bulk.

    All written without hesitation for "longhand" syntax. (and btw, its "if ( NULL == var ) " to those that care). The code optimized fine, with just a few choice inlines we got to stick. No reg vars, no assembly piles littering the code.

    But this was an in-house business app, and the lifecycles / requirements are different than other products. However, because of the nice algorithms, optimization wasn't difficult, and didn't rely on code tricks. If you're squabbling over code tricks for optimization, you're choosing the wrong algorithm, to me.

  61. illegal optimization there, for C at least by r00t · · Score: 3, Informative

    If by "const references" you really mean a
    C++ reference, OK. If you mean a pointer though,
    and you use C, the compiler is prohibited from
    performing this optimization unless you also use
    the "restrict" keyword.

    Since you did mention "restrict", it appears that
    you are working with C. "restrict" is not a C++
    keyword.

    BTW, inlinedamnit is __attribute__((__alwaysinline__))
    for gcc and __forceinline for Microsoft.

  62. Rules for writing fast code (aka optimization) by MSBob · · Score: 3, Insightful
    First: Avoid doing what you don't have to do. Sounds obvious but I rarely see code that does the absolute minimum it needs to. Most of the code I've seen to date seems to precalculate too much stuff, read too much data from external storage, redraw too much stuff on screen etc...

    Second: Do it later. There are thousands of situations where you can postpone the actual computations. Imagine writing a Matrix class with the invert() method. You can actually postpone calculating the inverse of the matrix until there is a call to access on of the fields in the matrix. Also you can calculate only the field being accessed. Or at some sensible threshold you may assume that the user code will read the entire inverted matrix and you can just calculate the remaining inverted fields... the options are endless.


    Most string class implementations already make good use of this rule by only copying their buffers only when the "copied" buffer changes.

    Third: Apply minimum algorithmic complexity. If you can use a hashmap instead of a treemap use the hash version it's O(1) vs Olog(n). Use quicksort for just about any kind of sorting you need to do.

    Fourth: Cache your data. Download or buy a good caching class or use some facilities your language provides (eg. Java SoftReference class) for basic caching. There are some enormous performance gains that can be realized with smart caching strategies.

    Fifth: Optimize using your language constructs. User the register keyword, use language idioms that you know compile into faster code etc... Scratch this rule! If you're applying rules one to four you can forget about this one and still have fast AND readable code.

    --
    Your pizza just the way you ought to have it.
  63. Screw comments by rs79 · · Score: 3, Insightful

    "My rule is never comment what the program does, comment why it does it."

    Bah. Comments lie. Code never lies.

    --
    Need Mercedes parts ?
  64. The never overused example that I have by roman_mir · · Score: 3, Informative

    I got this job as a contractor 4 years ago now where the project was developed by over 30 junior developers and one crazy overpaid lady (hey, Julia,) who wouldn't let people touch her code so fragile it was (and it was the main action executor,) she would rather fight you for hours than make one change in the code (she left 2 months before the project release.) Now, I have never witnessed such monstrocity of a code base before - the business rules were redefined about once every 2 weeks dor 1.5 years straight. You can imagine.

    So, the client decided not to pay the last million of dollars because the performance was total shit. On a weblogic cluster of 2 Sun E45s they could only achieve 12 concurrent transactions per second. So the client decided they really did not want to pay and asked us to make it at least 200 concurrent transactions per second on the same hardware. If I may make a wild guess, I would say the client really did not want to pay the last million, no matter what, so they upped the numbers a bit from what they needed. But anyway.

    Myself and another developer (hi, Paul) spent 1.5 months - removing unnecessary db calls (the app was incremental, every page would ask you more questions that needed to be stored, but the app would store all questions from all pages every time,) cached XML DOM trees instead of reparsing them on every request, removed most of the session object, reduced it from 1Mb to about 8Kb, removed some totally unnecessary and bizarre code (the app still worked,) desynchronized some of the calls with a message queue etc.

    At the end the app was doing 320 and over concurrent transactions per second. The company got their last million.

    The lesson? Build software that is really unoptimized first and then save everyone's ass by optimizing this piece of shit and earn total admiration of the management - you are a miracle worker now.

    The reality? Don't bother trying to optimize code when the business requirements are constantly changing, the management has no idea how to manage an IT dep't, the coders are so nube - there is a scent of freshness in the air and there is a crazy deadline right in front of you. Don't optimize, if the performance becomes an issue, optimize then.

  65. Re:Clear Code - Boeing by Sponge+Bath · · Score: 5, Funny
    when that last engineer fills up the crapper, does the bathroom door look thus trapping him inside?

    HAL! Open the bathroom door!

    I'm sorry Dave, you shouldn't have had that last burrito.

  66. Re:(ptr == NULL) is wrong in C, bad in C++ by neil.pearce · · Score: 2, Informative

    Paradox man, you're wrong. You are so wrong.
    Trust me - or not, just PLEASE google for the C++ FAQ, and read what they have to say about NULL and the null-pointer...
    Then, google for any C/C++ spec you can grab (without having to payout $200 for) and check what they have to say...
    Then google for the source code of GCC/TCC (nice and complete) and examine it...
    Then try to explain how "if (ptr)" works using your logic...
    It will enlighten you as to why "NULL" MUST always be defined as 0, not just as a "convention", and why comparing *ANY* pointer to 0 is strictly MOST necessary and GUARANTEED allowable and ABSOLUTELY FUNDAMENTAL to all C/C++ compilers.
    Learn the difference between NULL (always 0) and the null-pointer representation (any bit pattern) and why that matters not whether your system base address (0) is a valid memory address of not.
    Incidently, look up the specification for the Motorola 680x0 processor. Memory address (bytes) 0 to 8 are NOT valid. They are BY DEFINITION the initial stack pointer and code start addresses. It matters not...

  67. Re:Not always. by shaitand · · Score: 2, Insightful

    I do too. Unfortunately some of the coding standards floating around make code very difficult to write and to read. There are people claiming that mixed case is a good idea.

    Dear god no, mixed case leads to gobs of errors from nothing more than incorrect case. All code should be lowercase unless some idiot has set an ancient precedent that Thingy(R) should always be all caps, period. This one thing can double the speed at which you write and debug code.

    Next is this BS about self-documenting code. Code is not meant to be self documenting. Proper scoping will prevent names from clashing. Write the most efficient function you can and choose names that make sense in the smallest scope possible.

    And then *gasp* COMMENT the code well. You can even include comments near where a variable or function is to indicate in plain English what it is for! Believe it or not, code should not be self commenting, code is not a spoken language and is a poor medium to use to express messages between people who speak one. Nothing works better than your actual spoken language in complete sentence structures in a comment to remind you what a variable or function is or what a block of code does.

    By_using_variable_nms_that_dnt_lk_like_this 40 times in 6 lines of code you will save enough time writing those 6 lines that you can add a nice comment that says # vnameshort is used to demonstrate a horribly verbose and lengthy variable name in this function. and please for god sake comment EVERY call of a function that is not part of the standard c libraries within 20 lines explaining where it came from! Doing this will not only easier for people who know the project well to see what is happening and where to refer to but it will also help those who are NOT familiar jump in and possibly change one thing.

    Believe it or not, I do not want to read your 100,000 lines of source to make one change. I want to be able to look at the main routine and b-line right from there to the portion of the code I need using the commented function calls.

  68. Must be nice by peccary · · Score: 4, Insightful

    one product
    one customer
    420,000 lines
    260 staff
    no competition
    no trade shows
    no salespeople selling new features that have never been discussed

    It's interesting to talk about their attention to detail, but to hold it up as a model for all software development neglects to consider that they are working under an entirely different set of constraints from most everyone else.

  69. C and "flexibility" of expression operators by GunFodder · · Score: 4, Insightful

    I think the example is fine; you just displayed an assumption that highlights one of the quirks of C.

    ! means "not" or "inverse of"; it is a boolean function. The variable ptr is a pointer; it is a reference to data, which means it isn't really data itself. !ptr shouldn't compute; a boolean operator should only work on boolean data. But C logical comparators are designed to work on everything. You are just supposed to know that 0 == NULL == false. This supposition is totally arbitrary and doesn't hold up in any language with strong typing.

    This is what makes C difficult for beginners. Bad code compiles even though it has logical flaws, and ends up failing in mysterious ways.

    The second case makes more sense. Equality is an operator that should work on all types of data. NULL is necessary if you are going to abstract data through the use of pointers or objects. Doing away with NULL would be equivalent to eliminating true and false and using 1 and 0 instead. Or eliminating strings and using sequences of ASCII codes. These substitutions are technically correct but in reality they make code unreadable.

  70. Just optimize for the "big picture" by Jugalator · · Score: 3, Interesting
    There's often no point in fiddling around with details, and you should instead focus on optimizing for "the big picture", e.g. whether you should really re-establish a database connection each time a user selects OK in a dialog box.

    As for simple code optimizations, here's what a modern compiler (Microsoft Visual C++ .NET 2003 in this case) optimize code as: (yes, I've checked these myself as I've been writing this post)
    for (int i = 0; i < 5; i++)
    {
    int j = 42;
    if (j == 13)
    {
    printf("j is %d", j); j = 42;
    }
    }
    return 0;
    ... optimized to ...
    xor eax, eax
    ret 0
    In other words, it basically threw away all that code since the program wouldn't make use of any values that would be calculated there. And this:
    for (int i = 0; i < 100; i++)
    {
    int j = 42;
    i += j;
    }
    printf("i is %d", i);
    return 0;
    ... optimized to ...
    push 129
    push OFFSET FLAT:??_C@_07JEGIODIB@i?5is?5?$CFd?$AA@
    call _printf
    add esp, 8
    xor eax, eax
    ret 0
    Do you see what that means -- yep, the compiler understood that the resulting value would be 129 by analyzing the for loop and simply just push that value onto the stack as a parameter to printf. It basically optimizes to:
    printf("i is %s", 129);
    return 0
    That's probably considered some simplistic analyzing too, by today's compilers. ;-)
    --
    Beware: In C++, your friends can see your privates!
  71. Dear Lord by sholden · · Score: 4, Insightful

    Ten years of programming in the language and you:

    1) Don't know when two things are obviously equivalent to any non-brain dead compiler.

    2) Think something other than readability matters.

    3) Think the non-idiomatic way of doing something is more readable.

    But I'm sure I'm just repeating the comments I can't be bothered reading.

  72. Re:Not always. by EsbenMoseHansen · · Score: 2, Interesting
    why, oh why, is NULL considered to be more clear than 0?

    In C, this is because 0 != NULL. NULL = (void*) 0. This makes a difference in function calls, where calling myfoo(int a) with myfoo(NULL) is a compiler error/warning, but myfoo(0) is legal.

    In C++, NULL = 0. Really. Here's the header from gcc (well, really the kernel):

    #if defined(__cplusplus)
    #define NULL 0
    #else
    #define NULL ((void *)0)
    #endif

    This is because C++ has points to members, I believe (not sure, don't use void* pointers). Instead I use this struct, which IMHO should be included in STL (slightly shortened in the interest of brevity, and written from memory, so may not compile):

    struct Null_ {
    template<typename T>
    operator T*() { return 0; }

    template<typename T, typename S>
    operator S::T*() { return 0; }
    } my_null;

    The first member ensures that my_null can be converted to any pointer other than pointer-to-member, and the last one takes care of those. This method makes the C case above work as it should, i.e. give an error.

    As for clarity, it separates two concepts: The NULL pointer (a pointer pointing to nothing) and 0 (an integer).

    As an aside, I actually prefer !p, since it say to me "If p not a valid pointer....". But I can handle both :)

    --
    Religion is regarded by the common people as true, by the wise as false, and by rulers as useful.
  73. Get the answer for yourself!! by Ninja+Programmer · · Score: 3, Insightful
    Saravana Kannan asks: "I have been coding in C for a while (10 yrs or so) and tend to use short code snippets. As a simple example, take 'if (!ptr)' instead of 'if (ptr==NULL)'. The reason someone might use the former code snippet is because they believe it would result in smaller machine code if the compiler does not do optimizations or is not smart enough to optimize the particular code snippet. IMHO the latter code snippet is clearer than the former, and I would use it in my code if I know for sure that the compiler will optimize it and produce machine code equivalent to the former code snippet. The previous example was easy. What about code that is more complex? Now that compilers have matured over years and have had many improvements, I ask the Slashdot crowd, what they believe the compiler can be trusted to optimize and what must be hand optimized?"
    Most compilers come with something called a disassembler. Or better yet, you can trace the code with an assembly level debugger. If you want to know whether or not your compiler produces good code, why don't you just look at your code and find out? I'll bet dollars to donuts that you have one of these tools sitting on your hard drive that will tell you what your compiler did. Seriously, if you don't know how to get the answer to the question for yourself, then you don't deserve to know the answer.

    Most compilers today will get all the simple stuff like if (!ptr) vs if (NULL == ptr) optimization. Its the more complex things that the compiler cannot "prove" where it has trouble. For example:

    void h(int x, int y) {
    for (i=0; i < N; i++) {
    if (0 != (x & (1 << y))) {
    f(i);
    } else {
    g(i);
    }
    }
    }

    Very few compilers will dare simplify this to:

    void h(int x, int y) {
    if (0 != (x & (1 << y))) {
    for (i=0; i < N; i++) f(i);
    } else {
    for (i=0; i < N; i++) g(i);
    }
    }

    Because the compilers have a hard time realizing that the conditional is constant and should be hoisted to the outside of the for loop. The compiler has the opportunity to perform loop unrolling in the second form that its may not try in the first instance.

    You can learn these things from experience, or you can simply figure it out for yourself with the afore mentioned decompilation tools.
  74. Re:Not always. by BasilBrush · · Score: 2, Insightful
    I'd never employ you. You are wrong on just about every point in that post. You sound like you've not been through many code review processes, if any.

    If you are serious about coding, I recommend you pick up a copy of the book "Code Complete" and read it cover to cover. You need it.

  75. Never do (x == y) by zapatero · · Score: 2, Funny

    Oh you are so right. And as a corrolary never do if (x == y), because with both sides being variables one day you'll write (x = y), and (y = x) wont save you.

    The recommended way for (x == y) is
    if ( log(x) == log(y)) All the real good programmers that read magazine articles are doing this.

    And anyway, real numbers are more precise than integers. So in the case of x and y being integers its more precise using the log of the value.

    Never mind that gcc since 2.96 can issue warnings (or error with -Werror) and that languages like Java don't even allow assignments inside if(...), it's still good to practice this sound magazine article advice.

    In fact never program. Because one day you'll enter a typo, and you might have a bug, and so you should never program.

  76. Trusting the compiler will become very important by Mr_Huber · · Score: 2, Interesting

    Consider all the hype last week about the cell processor. Here is a processor in which the CISC optimizing portions have been removed, trusting the compiler to create pre-optimized code. The cell processor will run this code blindingly fast and with no modification. The compiler must be a smart optimizer. IBM, Toshiba and Sony are betting a lot on a smart optimizer. I'm guessing they won't be disappointed.

    Further, consider the Parrot system to be used by Perl, Python and Ruby. There's a strong similarity here to the cell system. All three languages are to be compiled to a common register-based representation. That representation is to be optimized by the compiler before execution. They chose this model because w we have decades of research on optimizing code for register based computers (as opposed to Java's stack based computer).

    In short, some very large, very important projects already have a lot of faith in these optimizers. They are not going away. I suggest the best approach is to work with them.

    So how do you cooperate with your optimizer? Write cleanly and clearly. Don't try to outsmart the optimizer, because if you do so, your code will most likely be slower, not faster. And don't do any work until you need to. Write the project correctly and clearly, then profile. If you need to modify things, then you have a working baseline to compare your optimizations with.

    Finally, when you get the faster version, check it in, then refactor the design to something reasonable, rechecking the speed as you do so. Ideally, for a small performance hit, you can end up with fast, efficient and easy to maintain code.

  77. Re:Not always. by clarkcox3 · · Score: 2, Informative
    In C, this is because 0 != NULL. NULL = (void*) 0

    Actually, in C, NULL can be (0), just like in C++

    This is because C++ has points to members, I believe (not sure, don't use void* pointers).

    Actually, it's because, in C++, there is no implicit conversion from (void*) to any other pointer type; as there is in C

    --
    There are no tiger attacks in my area and it's all because this rock I'm holding keeps the tigers away.
  78. Re:Not always. by Foz · · Score: 2, Insightful

    Bullshit. He's spot on in many cases (although admittedly a tad overzealous).

    Comments should be used LIBERALLY, albeit intelligently as well. If you do something that isn't intuitively obvious to even the most casual observer, just take 30 seconds to write a fucking COMMENT explaining why you did what you did.

    Believe it or not, eschewing comments because "oh, well, if you want to understand it just read the code" just pisses those of us off who have to come along and clean up your miserable excuse for a codebase... and it sure as hell doesn't prove how studly a programmer you are.

    That doesn't mean half your codebase should be comments, but it does mean that you should at least make a passing nod to demystifying your own attempts at cleverness. I have lots of better things to do than to spend all fucking day picking apart your rabbit's nest of code before I can make a change, add a feature or fix a bug.

    People that honestly believe that "if it's well written it doesn't NEED comments" should be strangled with their mousecord and hung in their cubicles as a warning to the rest.

    -- Gary F.

  79. should you be optimizing? by nerdsv650 · · Score: 2, Informative

    A couple of points.

    First off *any* compiler will make that particular optimization.

    You should only think of instruction level optimization when you know with certainty that it will pay off, for example because you've run your code under a profiler and found the areas where it will actually make a difference. Once you've found the (probably tiny) areas where optimizing actually helps, do whatever it takes, and document your reasons as well as your methods.

    You can always ask your compiler to output assembly and look it over, if you aren't fluent in your proc's assembly you probably shouldn't be trying to out-optimize the compiler anyhow.

    That being said, "if (!ptr)" is legitimate and bears a different connotation from "if (ptr == NULL)", at least in my mind. One is truth, the other is zeroness. In some cases the former is actually the more obvious test. There are also cases where compactness yields more readable code because the whole idea fits in a space easily acquired at a glance, for example, "if (structp && structp->member == VAL)" is natural and obvious to anyone who's been at this for any amount of time.

    All of this, of course, IMO.

    -michael

  80. Once you decide to optimize... by LoveMe2Times · · Score: 3, Insightful
    I'm going to presume that you've *already* picked a reasonably effecient algorithm, 'cause otherwise there's no point. Second, I'm going to presume that you've already run the profiler, so you know which lines of code are important.

    Here's my "guide to optimizing":

    1) Are you disk I/O bound? You might need to switch to memory mapped files, or you might need to tweak the settings on the ones you have. You might need to use a lower level library to do your I/O. Many C++ iostreams implementations are slow, and many similar libraries involve lots of copying.

    2) Are you socket I/O (or similar) bound? If so, you may need to rewrite with asynchronous I/O. This can be a PITA. Suck it up.

    3) Are your threads spending all their time sitting in locks waiting for other threads? One, make sure you're using an appropriate number of worker threads optimized by the number of CPUs the host has. If you've already got the right number of threads, this can be a really tough decision. Presumably, the threads are helping your program readability, and trying to rework things into fewer threads is often a *bad idea*.

    4) Are you spending all your time in malloc/new/constructor free/delete/deconstructor? Maybe you need to keep things on the stack, use a garbage collector, use reference counted objects, use pooled memory techniques, etc. In the right places, switching from some "string" library to const char* and stack buffers can give a huge benefit. Make sure, of course, that you use the "n" version of all standard string functions (the ones that take the size of the buffer as an argument) to avoid buffer overruns.

    5) Are you spending all of your time in some system call? Like maybe some kind of WriteTextToScreen or FillRectangleWithPattern type of thing? For drawing code in general, try buffering things that are algorithmically generated in bitmaps, and only regenerate the parts that change. Then just blit together the pieces for your final output. Perhaps you need to rely on hardware transparency support for fast layer compositing. You might need fewer system level windows so you draw more in one function. Maybe you need to reduce your frame rate.

    6) Are you using memcpy as appropriate?

    If any of the previous items are true, you have no business worrying about the compiler. However, once you've gotten this far, you can start worrying about optimizing your code line by line.

    7) Since you've gotten this far, the line(s) of code you're worried about are all inside some loop that gets run. A lot. They may be inside a function that's called from a loop too, of course. So, a few things to consider. A) You may need to use templates to get code that is optimized for the appropriate data type. B) You may need to split off a more focused version of the function from the general purpose function if it's also used in non-critical areas. This has negative maintainance ramifications. C) Do the bonehead obvious stuff like moving everything out of the loop that you can. D) Look at the assembly actually generated by your compiler. If you're not confortable with this, you have no business doing further optimization.

    After looking at the assembler, then you'll know if the following are important. In my experience, they are.

    1) Change array indexing logic to pointer logic:

    MyType stuff[100];
    for( int i = 0; i < sizeof(stuff) - 1; i++)
    {
    stuff[i] = abs(stuff[i+1]/PI);
    if (stuff[i] < 0)
    stuff[i] = 0;
    else if (stuff[i] > maxval)
    stuff[i] = maxval;
    }

    can change to:

    MyType stuff[100];
    for( MyType* ptr = stuff; ptr < &stuff[98]; ptr++)
    {
    *ptr = abs(*(ptr+1)/PI);
    if (*ptr < 0)
    *ptr = 0;
    else if (*ptr > maxval)
    *ptr = maxval;
    }

    This eliminates lots of redundant addition. All of those stuff[i] = val type of statements tend to generate:

    mov

  81. Re:Not always. by Foz · · Score: 5, Insightful

    No, you're adopting a black or white approach. You are, in essence, saying that you don't need to comment at all. The original poster was saying that comments needed to be everywhere, on everything. I believe in a middle ground approach.

    I comment things that are non intuitive. I comment things that I *think* may be non intuitive. I comment things that I think someone else might have some difficulty understanding, because I happened to be deep into a code burn and consequently wrote something pretty tight, pretty sweet, but also pretty obfuscated. Finally, I comment things that I think *I* may not understand when I go back and look at the code again 3 months from now.

    I don't comment every single line... I don't comment simple data structures, loops "/* this is a for loop using the integer variable I */" etc which would be stupid. I do however disassemble the complex portions of my code, describe how I'm dispatching events and best of all *why* I decided to do things a certain way instead of a different way.

    I have, however, been handed 30k lines of code with zero documentation and not a single comment anywhere in it, with absolutely no clue at all how it worked and no access to the original programmer and been told "We need such and such fixed|updated|added by friday" and had to spend the entire week basically tracing every single line of code to figure out that the original programmer must have been smoking crack with NO indication of why he wrote things how he did and NO help when he decided to be exceedingly "clever"
    in his code. That time was wasted.

    Would it have killed him to simply put a comment block explaining his event dispatch model? Or to tell me what his functions and methods did and best of all why they did it?

    There *is* a middle ground, believe it or not.

    -- Gary F.

  82. No, no, no! Semantics... by Catullus · · Score: 2, Insightful

    The grandparent poster was completely right. The implied meaning of "if (!ptr)" is "if ptr is not valid". The fact that NULL is equivalent to "not valid" is essentially irrelevant to understanding the statement.

    The key aspect - and the interesting thing - about coding style is that you are writing something for other humans to read. Everything you write contains hints to those humans about what you mean. Saying "a == NULL" is subtly different to saying "!a".

    Being able to read programs and pick up stuff like that is possibly something that takes a long time to learn, but (imho) it's very important. Code written by true experts is fascinating because of the way that they make the meaning of what they're writing clear.

    This is why (again imho) programming is an art, not a science.

    Incidentally - pointers are not references to data. They are data like anything else. Unless you understand this, pointers to pointers are fairly meaningless. Always remember: in C, everything is a bunch of bytes.

  83. Re:Code, Compiler and Optimization by omb · · Score: 3, Insightful
    As someone who has been in the industry for a long time:

    This issue is in like this,

    You need to understand the language, both syntax AND semantics you are using

    this ranges from the simple to mind-bending e.g. C++ (I am convinced that not even Bjarne Stroustrup understands this evil language);

    at that point you have two bi-furcations (a) interpreted languages eg Java, Perl, PHP and Python -v- (b) cpmpiled languages, and (c) finally DIY (do it your self) Assembler

    So: what does it amount to in practice? A) Rock Bottom, understand the architecture, including virtual memory, architecture and instruction set issues, read and understand the chip data sheet. Hard! See bottom line, architecture dependand code in Linux, bsd ...

    B) use 'gcc -S' and write the code in C, hand improve the assembler output, this is what I normally do, but you need to keep an open mind otherwise you miss things, I once took a compute intensive algorithm for the M68020 and made it run 10'000 times faster using this approach

    C)consider hardware optimisation; strictly price/performance.

  84. Finally, a story that my signature works well with by smcdow · · Score: 3, Interesting

    I've been using it for a while...

    --
    In the course of every project, it will become necessary to shoot the scientists and begin production.
  85. Never do (x==NULL), do (!(x-NULL)) by eXocomp · · Score: 2, Funny

    "if (!(x-NULL))" is not only foolproof, but much easier to understand!

  86. Re:Clear Code - Boeing by flargleblarg · · Score: 2, Funny

    So how many dumps does it take to fill up the crapper tank?

    Man, due to budget cuts, I'd hate to be the one guy whose job that is.

    "Hang in there, you only have 17 craps to go. Here, have another burrito."

  87. Optimization by AaronW · · Score: 3, Insightful

    In terms of optimizing, generally compilers do a pretty good job, however there are several areas that no compiler I know of can help.

    1. Choose the right algorithm. For example, in an embedded project I worked on an engineer used a linked list to store thousands of fields that must be added and deleted. While adding is fast, it didn't scale for deleting. Changed it to a hash table and it sped it up significantly.

    2. Know your data and how it is used. Knowing how to organize your data and access it can make a huge difference. As a previous poster pointed out, sequential memory accesses are much faster than random accesses. I had to do some 90 degree image rotation code. The simple solution just used a couple for loops when copying the pixels from one buffer to another. In another, I took into account the processor cache and how memory is accessed and broke it down into tiles. The first algorithm, while simple and elegant ran at 30 frames per second. The other ran at over 200 frames per second. Looking at the code the first algorithm should be faster since the code is simpler. Both algorithms operate in O(N) time, where N=width * height.

    Further optimization attempts to hint to the CPU cache about memory made no difference (Athlon XP 1700+). The only possible way I see to speed it up further would be to write it in hand-coded assembler.

    3. Reduce the number of system calls if possible. Some operating systems can be very painful when calling the kernel. Group reads and writes together so fewer calls are made.

    4. Profile your code to find bottlenecks.

    5. Try and keep a tradeoff between memory usage and performance. A smaller tightly packed data set will execute faster with CPU caches and will reduce page faults when loading and starting up.

    6. Try debugging your code at the assembler level, stepping through it. It will help you better understand your compiler.

    7. Don't bother trying to optimize things like getting every ounce of performance when the next function you call will be very slow. I.e. in one section of MS DOS's source code which was hand-coded assembly language it was calculating the cluster or sector of the disk to access. First the code checked if it was running on a 16-bit or 32-bit CPU. Next it took the 16-bit or 32-bit path for multiplication, then it read from the disk. Why the hell write all this code to check the CPU if it's 16 or 32 bit for the multiply when the frigging disk is going to be slow. They should have just stuck with the 16-bit multiply rather than be clever.

    In general applications with GCC, I rarely see much difference between -O2 or -O3. For that matter, I often don't see a noticable difference between -O0 and -O3 for a lot of code.

    I only see improvements in some very CPU intensive multimedia code. I also saw a significant improvement in some multimedia code when I told the compiler to generate code for an Ultrasparc rather than the default, but that's because the pre-ultrasparc code didn't use a multiply instruction.

    -Aaron

    --
    This post is encrypted twice with ROT-13. Documenting or attempting to crack this encryption is illegal.
  88. Re:Not always. by Impy+the+Impiuos+Imp · · Score: 2, Interesting

    > People that honestly believe that "if it's
    > well written it doesn't NEED comments"

    They are lazy, and lack attention to detail. This is a mental escape on their part that assuages their small-frog egos.

    --
    (-1: Post disagrees with my already-settled worldview) is not a valid mod option.
  89. Do not prematurely optimize by dumbnose · · Score: 3, Insightful
    Writing less clear code because you believe it is more efficient is the worst thing you can do for your code. It will only cause bugs in the short-term and create less manageable code in the longer-term.

    Do not perform minor optimizations without first: a) Determining there is a performance problem b) Profiling your code to determine what areas should be optimized.

    This does not mean that you should choose naive algortithms for the problem at hand. Choosing the proper algorithm for the problem at hand is always important.

    Hand-optimized code should be reserved for those times when you have profiled your code with reasonable inputs and have shown that the lack of clarity is compensated for by the increased performance.

    The example you gave is a perfect example of a hand optimization that is completely worthless with today's compilers.

  90. Amen by Bozdune · · Score: 2, Informative

    Let's not forget how long it took them, either. I worked with some of the Shuttle programmers. I shared an office with one pudgy little 40-something bald guy who wrote about three lines of code per month. He had a big loose-leaf notebook full of all his test cases and his test jigs and his interfaces and his error checks. He worked for another guy who used to hold 1/2 day meetings every two days. In the time I shared a cubicle with him, probably 3 months, he had accomplished a whole lot of nothing.

    As far as how together and structured the Shuttle group was, I remember the day there was a head crash on the 3330 drive that held all their source code. It was like turning over an ant nest, programmers scurrying around the halls screaming, etc. Don't believe everything those people write about how well they were organized and how wonderful everything was.

  91. Readibility by Kell_pt · · Score: 2, Informative

    I must say I don't agree with the author's remarks on readability. I use
    if ( !ptr )
    throughout my code for ages and always felt that to be far more readable, and so do my colleagues. It's also faster to type.
    It reads "if no pointer" which is far understandable than "if pointer is null". Because pointers aren't really null, they are zero.

    Mostly, it's just a matter of style. Imho, if you have trouble reading either of these though, you're using the wrong language - for your own safety stay away from Perl aswell. ;)

    --
    "I don't mind God, it's his fan club I can't stand!" E8
  92. /. posters by Saville · · Score: 4, Insightful

    "I ask the Slashdot crowd, what they believe the compiler can be trusted to optimize and what must be hand optimized? Give examples of code optimizations that you think the compiler can/can't be trusted to do."

    Somehow 99% of the readers took this to mean "What is the difference between NULL and the zero bit pattern and do you think it is a good idea to write clear code and do the profile/algorithm change cycle until there is nothing left to optimize or should I write low level optimized code from the start?"

    sigh.. I've only found two comments with code so far after going through hundreds of posts. This is possibly the worst signal to noise ratio I've witnessed on /.

  93. HLSL by Saville · · Score: 3, Informative

    As far as I'm concerned compilers are better than 99% of the programmers out there. Just write clear code and let the compiler do it's trick. However there are a couple cases where things aren't automatically optimized that I can think of.

    It's not really a coding trick like an XOR swap, but most compilers don't yet seem to fully unroll parallel loops into good SIMD instructions or multiple threads.

    The only time I've needed to bother to look at assembly output in recent years (other than debugging a release mode program) is when writing HLSL shaders. HLSL is the high level shading languge (C like) for shaders that is part of Direct3D 9. HLSL can be compiled to SM1, SM2, or SM3 assembly.

    With pixel shader 2.0 you've only got 64 instruction slots, and some important instructions like POW (power), NRM (normalize), and LRP (interpolate) take multiple slots. 64 slots is not enough for a modern shader. I curse ATI for setting it bar so low. ;)

    There are two flaws I've found with the Dec 04 HLSL compiler in the DirectX. Sometimes it will not automatically detect a dot product opportunity. I had some colour code to convert to black and white in a shader and wrote it as y = colour.r*0.299 + colour.g*0.587 + colour.b*0.114; as I thought that was the most clear way to write it. Under certain circumstances the compiler didn't want to convert to a single dot instruction so I had to write as y = dot( colour.rgb, half3(.299h, .587h, .0114h)); I'm not sure if that bug still exists in the current compiler release or not.

    Another is often a value in the range of -1 to +1 is passed in as a colour, which means it must be packed into 0-1 range. To get it back you've got to double it and add 1.
    a = p*2+1; gets converted into a single MAD instruction which takes one slot.
    a = (p-0.5)*2; gets converted into an ADD and then a MUL.

    Also conventional wisdom says you've got to write assembly to get maximum performance out of pixel shader 1.1 as it is basically just eight instruction slots. I don't have any snippets to verify this though.

    I think this thread demonstrates that either compilers are mature enough you don't need any code tricks to help them do their job or /. posters just aren't aware of the short commings of compilers (see first sentence of this post) and would rather post obvious advice than not post at all. :)

  94. In most cases by Z00L00K · · Score: 3, Informative
    I try to write code that is simple to read and avoid complex statements. This is often easily optimized by the compiler and more important readable for whoever is doing maintenance on the code.

    For the rare performance critical parts it is however worth the effort to try various constructions to get the best performance out of the code. The most problematic issue is to identify the hotspots in the code and figure out which variables that should be declared as 'register' and those that shouldn't. Ordering of statements are also important in order to match the various performance improvments the CPU can offer. One very good document on this is actually found at AMD.

    One code construct that I am using that I found is very useful is to place the matching '{' and '}' in the same column in the code. This eases the effort trying to find where a block begins.

    Example:

    if (a == b)
    {
    printf("Hello!\n");
    }
    In my opinion this produces code that has an improved readability compared to the constructs placing the '{' on the same line as the if-statement where it is much easier to miss.
    --
    If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
  95. Does anyone think this even matters? by Bruce+Perens · · Score: 2, Insightful
    People have 4 GHz CPUs these days and somebody is worried about the difference between !p and p==NULL? If any compiler actually assembles code with a speed difference for those examples these days, it might well be that the speed difference is one billionth of a second. And even if that code is in a tight loop, it's entirely irrelevant given that the memory bandwidth is probably the governing factor rather than how fast the CPU can do integer vs. 0 tests.

    Hey, my phone has a 400 MHz processor.

    Bruce

    1. Re:Does anyone think this even matters? by R1ch4rd · · Score: 2, Informative

      That's 99% true, but then there are those 1% applications were it does matter. I'm writing real-time computer vision applications and 1/2 a millisecond still counts. And you have a piece of code running 1000's of times which MUST be as fast as possible. So it's a valid question after all. Richard

  96. If that's true.... by TheLink · · Score: 2, Interesting

    If it's 99% true, then perhaps more than 80% of programmers shouldn't be writing in C. (Judging from the posts on this discussion I think I'm right ;) ).

    Because IMO nowadays writing in C is usually a premature optimization.

    With all the GHz CPUs, higher level languages are often more than fast enough. It's usually the design and algorithms that you have to get right.

    The advantage of writing in a higher level language first is you write far fewer lines of code - esp if the Customers keep changing their minds every month.

    Optimizing at low levels only gives you linear improvements in speed. Doesn't help you if the system slows exponentially.

    What I mean by linear is:

    Say you use the same algorithm.
    #1: fast low level language, optimized.
    #2: in a fast low level language.
    #3: high level language.

    If #3 is 4 times slower than #1 in most cases it'll always be 4 times slower. Same if #2 is 10% times slower than #1.

    Whereas a high level optimization can gain you lots more.

    On a fair size complex system it's probably best to write stuff/modules in a high level language first and then replace them with C or hand assembly later if necessary.

    Maybe it is wasteful. But at least you can say to the people doing it - the informal spec is: "it's got to work exactly like what you are replacing - only faster". After all that module is already working :).

    Call the stuff in the high level language your pseudocode. The equivalent of the plastic/clay model or prototype.

    --
  97. !var is not always the same as var == NULL by flok · · Score: 2, Informative

    Why? There are platforms (maybe there were, not sure) where NULL is actually not the same as 0.

    --

    www.vanheusden.com - home of Multitail, HTTPing, CoffeeSaint, EntropyBroker, rsstail, bsod, listener, nagcon, nagi
  98. Re:Code, Compiler and Optimization by mobiGeek · · Score: 2, Insightful
    As someone else who has been in the industry a long time, I find that only a very small amount of code actually needs to be optimized in the method you mention above.

    The biggest problem I run into are programmers who "know the compiler" so much that they make impossible to decypher all-in-one-if-statement code blobs.

    Write the damn code in a clear and precise way. Compile and run it. If performance is an issue (which for the majority of s/w it is not), then profile the code and make sure you know where the problem is.

    Then, and only then, should the programmer consider rewriting code for optimization. And even then, often it is the algorithm that needs to be fixed, not the fact that the compiler's optimization is missing something obvious. These compiler thingies tend to to be pretty decent these days.

    One of my favourite quotes I share with new grads as they come on-board with their fancy compiler theory classes under belt:

    In "Literate Programming," Donald Knuth wrote "We should forget about small efficiencies, about 97% of the time. Premature optimization is the root of all evil."
    --

    ...Beware the IDEs of Microsoft...

  99. Re:Readibility vs null values by Kell_pt · · Score: 2, Interesting

    Given a pointer to an object, it is not the pointer which is null. The pointer is zero, it is the object which is null, seeing as it is impossible to obtain its value from a pointer with value zero. We just do the trick of using both pointer and its contents to represent incomplete information.

    The concept of NULL is an extension to the domain of a variable. It means "no value". In C/C++, we often think of the pointer as the object itself, and as such we do the little trick of using two different operations to get that valuable extension to the domain: we either read the value of the pointer (a memory address) and compare it to zero or we load its content ( the -> operator ). However, why doesn't one usually compare pointers to static values other than zero( eg, ptr != 3 )? In not doing it, we bring to light the fact that we're just using part of the domain of the pointer variable.
    To make this clear, think of what you'd have to do to have a null integer. In C you'd likely do:
    int * val = malloc( sizeof(int) );
    And then you'd use "val" for the null comparison and "*val" for the integer. Funny how in doing that you're spending more memory than if you did:
    typedef struct { int value; bool isnull; } NullableInt;
    NullableInt a;
    With this you'd spend 5 bytes per variable. With the other approach you spend 4 bytes per variable plus 4 bytes for the pointer, for a total of 8 bytes (on 32 bit architectures). :)

    Obviously, these considerations are a bit pointless, and one benefits little from them in the context of C/C++ programming. :=)

    On the other hand, some languages have specific support for nullable variables, without having to resort to pointers (at least syntactically). NULLs are famous in SQL, although they are also infamous for being used incorrectly many of the times. ;)

    --
    "I don't mind God, it's his fan club I can't stand!" E8
  100. Compiler wins by Lars+Clausen · · Score: 2, Insightful

    I go by the First Rule of Optimization: "Don't Do It" (occasionally, I will follow the Second Rule of Optimization: "Don't Do It Yet"). Two reasons:

    1) Hand-optimized code tends to be harder to write, debug, understand, and maintain.
    2) The compiler frequently does a better job anyway. Try comparing the standard strcpy function (while (*s != 0) *t++ = *s++;) with one that uses array indexing (while (s[i] != 0) { t[i] = s[i]; i++; }) using gcc -O3. On some versions and CPUs, the array-indexing code will actually use fewer instructions because the compiler gets more chances for optimization when you tell it that you're working with arrays. Pointer manipulation is for stupid compilers.

    Of course, compilers cannot save you from bad design. Make sure to think about your O() factors.

    -Lars

  101. Re:Not because of implicit conversions from void* by clarkcox3 · · Score: 2
    which could just as easily apply to (void*)0 as well, making C++ match C in this one case.

    It could, but it doesn't. The following is illegal in C++, period: char * c = (void*)0;

    --
    There are no tiger attacks in my area and it's all because this rock I'm holding keeps the tigers away.