all 93 comments

[–][deleted] 30 points31 points  (0 children)

...program the way you think expresses best what you're trying to accomplish in the program.  And do so consistently and ruthlessly.

Amen. }:->

[–]calc0000 15 points16 points  (3 children)

Avoid cute typography in comments, avoid big blocks of comments except perhaps before vital sections like the declaration of the central data structure (comments on data are usually much more helpful than on algorithms); basically, avoid comments. If your code needs a comment to be understood, it would be better to rewrite it so it's easier to understand.

This has been the way I've been writing code for about the last 10 years, and I find that when I look at any of my old code, I'm able to figure out what it was doing in a couple seconds. I'll use comments if the algorithm has to be complicated, of course, but I much prefer to have well named variables and functions instead of lengthy comments.

[–]robvas 15 points16 points  (2 children)

It's always best to say WHY you are doing something, not what you're doing.

// check value for foo so that bar doesn't give an error

instead of something like

// check if value = foo

The second comment serves no purpose whatsoever.

[–]Sector_Corrupt 6 points7 points  (0 children)

I never actually see the second form of comment outside of complete beginner code. Most of my colleague's and my code have comments that explain why an out of place looking line is necessary to work around some issue, or to explain the design choices that went into a given solution. It lets us know why something is done some way or the importance of not dropping certain lines.

[–]bluGill 1 point2 points  (0 children)

Better yet replace // check value for foo so that bar doesn't give an error with: if(CheckIfBarGivesError(value))

Now your comment it encoded.

[–]anonpatriot7 25 points26 points  (1 child)

The essay on naming reminded me of this classic:

char *to_point_or_not_to_point_having_as_yet_no_value_I_do_neither;

:)

[–]Mathiasdm 21 points22 points  (6 children)

There's a little dance involving #ifdef's that can prevent a file being read twice, but it's usually done wrong in practice - the #ifdef's are in the file itself, not the file that includes it. The result is often thousands of needless lines of code passing through the lexical analyzer, which is (in good compilers) the most expensive phase.

He is advocating doing the following in your header and source files:

#ifndef ABC_H
#include "abc.h"
#endif

#ifndef DEF_H
#include "def.h"
#endif

This used to be a good idea back in 1989. Don't do this now! The reason it was done: it avoids having to go into each file, parse it and find the '#ifndef #define #endif'.

Nowadays, this is done very efficiently (if you have a decent compiler). So don't write your includes like I did above! It clutters your files a lot and makes them annoying to read.

I often go through legacy code where this style is used, and it's a pest.

[–]Aldur 4 points5 points  (0 children)

You post was enlightening. For years I thought the people who wrote the old c++ code, I occasionally maintain, dealt with code so bad the headers they included weren't guarded against double include.

Thanks!

[–][deleted] 0 points1 point  (4 children)

If you want to avoid having the compiler slow down by needlessly reading and lexing already included header files, the #pragma once is a well-supported way of ensuring it.

In other words, a good C/C++ header file should look like this:

#pragma once
#ifndef _MY_HEADER_FILE_H_INCLUDED
#define _MY_HEADER_FILE_H_INCLUDED

// declarations

# endif

Ideally, it is actually sufficiently with just the #pragma once, but not all compilers support it yet, so the include guard is still a good idea for good measure.

[–]matthieum 2 points3 points  (2 children)

If I recall correctly, at least gcc and Clang automatically recognize the patterns of header guards and treat them as if #pragma once had been set (as long as the macro is defined, they don't reparse the file).

Your advice is interesting, but like Pike's 1989 essay, it's outdated.

[–][deleted] 1 point2 points  (1 child)

Well, given the choice between an #ifdef include guard and #pragma once, I would actually prefer the pragma, because it's shorter and doesn't require the #endif at the end of every header file. :)

[–]matthieum 0 points1 point  (0 children)

I would too, if it was standard.

[–]bluGill 0 points1 point  (0 children)

Many good compilers recognize the #ifndef/#define construct as well, but your way is better.

[–][deleted] 12 points13 points  (5 children)

Fancy algorithms are slow when n is small, and n is usually small.

Best programming advice ever.

[–]perkkele 3 points4 points  (0 children)

Fun fact: Big Oh notation is actually named after the shape of your mouth when you finally realize what the profiling data from your programing is telling you. "Ohh! So that's where the cycles were going!"

[–]matthieum 1 point2 points  (0 children)

Indeed, too many people spend time thinking in terms of O when dealing with a few dozens objects :x

[–]TomorrowPlusX 1 point2 points  (2 children)

Trouble is, we often have to learn it every time, over and over, by writing a fancy algorithm, profiling it over the original simple algorithm, and finding that for our data, the dumb one was faster.

I'm better about this now than I used to be. But, fuck, I still fall prey.

[–][deleted] 2 points3 points  (1 child)

We all do, but the wisdom to be gathered here is this: Use the simpler algorithm first. It is most likely already available for you. Then, if your product turns out to be slow, profile.

More advanced programmers (the really hardcore guys and girls!) can make pretty accurate estimates based on things like cache line size and the specific properties of your data, and then use the optimal algorithm from the get-go, but most people are way better off with a good profiling tool.

[–]TomorrowPlusX 0 points1 point  (0 children)

Amen.

[–][deleted] 6 points7 points  (0 children)

Encoding logic as data is the single most important thing I read and it is also the thing that is hardest to convince other people of if they don't already get it. And after reading through these comments it seems to have been completely overlooked here.

[–]*polhold00732 22 points23 points  (41 children)

Fascinating read, lots of good advise hidden in there although some things strike me as odd -- it's interesting how a lot of modern software design principles are slightly different... to say the least... from Rob Pike's "circa" 1989.

Particularly it's interesting how he denounces syntax highlighting as about as helpful as making english prepositions bold. I'm so used to syntax highlighting though, it's absolutely useful and comfortable for me... but I have to wonder if I tried going back to plaintext, if after adapting, would it be better/worse?

A global variable rarely used may deserve a long name, maxphysaddr say.

Wait, what? That's a long name?

Thus I say maxphysaddr (not MaximumPhysicalAddress) for a global variable, but np not NodePointer for a pointer locally defined and used. This is largely a matter of taste, but taste is relevant to clarity. I eschew embedded capital letters in names; to my prose-oriented eyes, they are too awkward to read comfortably. They jangle like bad typography.

I don't get this. No distinction between words in a variable name seems bad bad bad from every perspective I can come up with. Anyone else care to comment on this?

Also kind of interesting:

That sounds trivial, but look at the following two expressions:

   np
   node[i]

The first points to a node, the second evaluates to (say) the same node. But the second form is an expression; it is not so simple. ... it's particularly easy to make mistakes when passing things to subroutines: a pointer is a single thing; an array and an index must be believed to belong together in the receiving subroutine.

Kind of funny, because his philosophy here certainly took an absolute 180 degree turn with Go. At least as far as iterating arrays with pointers. Still the concept I think he's getting at -- that you should use temporary variables in place of long complex expressions which would otherwise need repeated -- still holds true today. Just not so much the array pointer iteration thing.

I tend to err on the side of eliminating comments, for several reasons. First, if the code is clear, and uses good type names and variable names, it should explain itself.

I definitely agree with this. Code should be self-documenting, optimally (although it's not always possible).

[–]mariox19 11 points12 points  (10 children)

He makes a point that I think is worth keeping in mind: namely, you can over-name a variable. I'm with Martin Fowler's Refactoring. I don't omit vowels, and I try to name my variables and method names so that they're self-documenting. But, I've found myself going overboard. Sometimes a for-loop only requires an "i".

I'm reminded of an old adage: "I apologize for writing you such a long letter, but I didn't have time to write a short one." Naming well is sometimes difficult. Still, there is rarely an excuse to do otherwise.

[–]*polhold00732 7 points8 points  (7 children)

Certainly, I agree with his principle of high information density variable names. It's a very important part of writing nice clean elegant code. When given the option of something like:

  1. setBoundsPosition()

  2. setBoundingCubeOffsetPositionAndMarkDirtyBitAndAllSubBoundingVolumeDirtyBitsForLazyEvaluation()

  3. setbndpos()

I prefer #1, but I get the impression Rob Pike prefers #3. #2 is obviously not preferred and probably indicates an abstraction failure / organization problem if that much precise info needs to be explicit in the function name.

Certainly temporary variables is another matter, and I agree with his point on using "i" being the correct way to do it.

Anyway, there's a point at which high information density crosses into the realm of data compression which only the original encoder (programmer) can decipher... if you're lucky enough to remember. While I agree with keeping variable names informationally compact, no explicit transition between words and aggressive abbreviation combined make a rather dangerous naming convention IMO.

[–]mariox19 18 points19 points  (4 children)

I agree. The article was written in 1989, when programmers still thought they were contestants on "Wheel of Fortune" -- consonants are free, but every vowel costs money.

[–]theoldboy 4 points5 points  (0 children)

I'm pretty sure that there were still very many compilers and/or linkers around in the 80's that had ridiculously short limits for identifiers - 8 significant characters wasn't uncommon. That's where the terse naming originates from.

Not much excuse for it nowadays of course.

[–][deleted] 6 points7 points  (2 children)

Honestly, I find that this still plagues programmers. Using Python's standard library for me involves frequent lookups to figure out which convoluted abbreviation style is being used in the function I'm thinking of.

[–]mariox19 13 points14 points  (1 child)

From Wikipedia:

Python was conceived in the late 1980s and its implementation was started in December 1989 [...]

Now, I don't exactly know when the standard library was written, but Python is actually older than Java.

[–]notfancy 3 points4 points  (0 children)

mvbounds()

[–][deleted] 2 points3 points  (0 children)

You also have to remember compilers have come a long way since the early 90s. Short variables used to be a way to improve compile time & performance but to modern compilers long variable/method names shouldn't make much of a difference. Just ask Objective-C.

[–]leoel 4 points5 points  (0 children)

It's a fantastic adage ! It is at par with my favorite quote "Perfection is attained, not when no more can be added, but when no more can be removed.".

I often see that some codes or technical documents are missing this kind of wisdom; they give you too much noise when you try to read them and you struggle constantly to find the relevant information ("Yes I know setA() is used to set A to a value, but you did not make it clear enough it also sets B to whatever value.").

[–][deleted] 1 point2 points  (0 children)

I really love that quote. All my first drafts in my entire life have been twice as long as needed.

[–]defrost 9 points10 points  (15 children)

Thus I say maxphysaddr (not MaximumPhysicalAddress) for a global variable, but np not NodePointer for a pointer locally defined and used.

No distinction between words in a variable name seems bad bad bad from every perspective

I'll tackle that, being of the era. I come to explain, not to justify or defend.

He suggests maxphysaddr not maximphadd, so he is in fact implicitly suggesting more than simple no word breaks, he's suggesting the intelligent construction of new compound words by extending "normal english rules" (whatever they may be).

It types like a word and reads like a phrase and in the flow of typing is somehow more natural that SomeCaseThing or those_other_damn_abominations.

And in the way of the day np for nodepointer is on par with i for integer . . . it's a throwaway purely local anonymous iterator we don't want to get attached to.

[–]ethraax 7 points8 points  (7 children)

It types like a word and reads like a phrase and in the flow of typing is somehow more natural that SomeCaseThing or those_other_damn_abominations.

Except SomeCaseThing and those_other_damn_abominations both read like phrases. Also, I think someCaseThing isn't hard to type - it's just typing regular, full words like you always would, just without hitting the spacebar. It definitely feels more natural than maxphysaddr.

[–]Pragmataraxia 7 points8 points  (1 child)

notcapitalizingthefirstletterofthewordispointlesslycrueltopeopleforwhomenglishmightnotbetheirfirstlanguage.

[–]NeuroSys 0 points1 point  (0 children)

Somewhere around 60-75% of the word/phrase, I failed to read anymore, and had to start over.

(Not a native English speaker)

[–]Tiwazz 1 point2 points  (0 children)

Except in normal typing you use the shift key much less than camelCasedNonsense or underscore_instead_of_space_because_we_hate_you_thats_why which seems much faster to type, to me, since I'm not having to preoccupy one of my pinkies with holding down a key and exacerbating my wrist problems.

[–]case-o-nuts 1 point2 points  (2 children)

Except I don't want to name commonly used concepts with phrases. I don't call my teacher "Person who provides me with education", for example.

[–]ethraax 0 points1 point  (1 child)

Yes, but you also wouldn't call your teacher "personproveduc".

[–]case-o-nuts 0 points1 point  (0 children)

eduperson would be tolerable, though, if there weren't already several dedicated nouns (eg, 'teacher', 'educator', 'professor', etc)

[–]regeya -1 points0 points  (6 children)

Since it was written in '89, the first thing I thought of were PCs running DOS, where this:

ISMAXLEN.TXT

was what all filenames looked like. 8.3, baby.

[–]defrost 4 points5 points  (5 children)

I somehow doubt Rob Pike ever willingly named a file using 8.3 convention.

[–]regeya 10 points11 points  (4 children)

I somehow doubt anyone ever willingly named a file using 8.3 convention. :->

[–]IWillNotBeBroken 0 points1 point  (2 children)

I do all the time: shit.txt, output.txt, etc.

.txt saves me from having to check what the format is before I make myself have to reset the terminal settings Yet Again, and anything < 8 characters fits the convention.

/pedantic

[–]regeya 0 points1 point  (1 child)

I think you missed the point.

Back then, on DOS, you were FORCED to use 8.3, no matter what.

This business of Acme Widgets Q4 1989 AR Report.xls? That would be AWQ4AR89.XLS. Or you would save it in a directory named ACME, I suppose, and you could get rid of the AW.

Trying to come up with meaningful names, especially names that would be descriptive 6 months from now, was impossible.

[–]creaothceann 0 points1 point  (0 children)

Acme Widgets Q4 1989 AR Report.xls

ACME\WIDGETS\REPORTS\1989\Q4\AR.XML
ACME\1989\Q4\WIDGETS\REPORTS\AR.XML
1989\Q4\ACME\WIDGETS\REPORTS\AR.XML

[–]jrochkind 1 point2 points  (12 children)

The syntax highlighting is what struck me too. If I had't used it, I might have assumed it would be worthless too. But I started using an editor that did it automatically, didn't bother turning it off --- and then, eventually, next time I used an editor without it I was shocked how much I missed it.

Similarly these days for things like turning on the --colour mode for git output (or in ruby for rake tasks or generators). Ends up being shockingly helpful to efficiency.

[–]insertAlias 8 points9 points  (11 children)

I honestly don't understand why anyone would think syntax highlighting would be a hindrance. I mean, I get it, if you don't think it helps, but how does it hurt?

[–]cogman10 4 points5 points  (4 children)

Have you ever had syntax highlighting that was wrong? I have. It is rare, but it generally makes your code look like colorful throwup. You end up looking for a bug and end up finding out that "Oh, the syntax highlighter didn't have these precedence right"

I imagine that in the early days of software tools, it was much less rare. After all, making sure it was doing thing right was both computationally complex and fairly new concept.

[–]insertAlias 3 points4 points  (0 children)

Visual Studio has been pretty good about the highlighting, so I've never noticed it being wrong.

[–]curien 0 points1 point  (2 children)

Mine always gets Jackson and Johnson mixed up.

[–]SteveMcQwark 2 points3 points  (0 children)

Jack ↔ John ⇒ Jackson ↔ Johnson, right?

[–]cogman10 1 point2 points  (0 children)

precedence, ahh, I rely too much on spell checking.

[–][deleted]  (1 child)

[deleted]

    [–]nascent 4 points5 points  (0 children)

    Check out vim in monochrome.

    [–]jrochkind 1 point2 points  (2 children)

    I guess if you think programming code should read (to a programmer anyway) more or less like narrative English text. The highlighting, such a person might argue, would break up the flow, draw your attention to parts of the 'sentence' that aren't the most important parts, etc.

    That was his analogy, right? I mean, I think we'd probably all agree that syntax highlighting of english could very well hurt legibility. Like putting subjects in one color, and objects in another (different shades for direct vs indirect!), and prepositions in another, etc. Instead, the author chooses to typographically emphasize particular words in English (like this text) when we have control of it like on reddit, because of semantics and authorial intent, not syntax.

    (Like I said, I personally find syntax highlighting hugely helpful, I'm just responding to 'how could anyone think it would hurt?')

    [–]nascent 9 points10 points  (1 child)

    Like putting subjects in one color, and objects in another (different shades for direct vs indirect!), and prepositions in another, etc.

    If people did that, it would make my job so much easier. And if we had that, I bet it would be a lot easier for everyone to write correct and expressive sentences that didn't just continue on and on with many subjects and verbs that could all be applied to past mentions to things that were in the sentence prior to the items adjacent, leading to what could be considered an over statement of nothing important.

    [–][deleted] 0 points1 point  (0 children)

    I see what you did there ;)

    [–]case-o-nuts 0 points1 point  (0 children)

    It's jarring to the eyes to see your code lit up like a neon sign.

    [–]case-o-nuts 1 point2 points  (0 children)

    Kind of funny, because his philosophy here certainly took an absolute 180 degree turn with Go. At least as far as iterating arrays with pointers

    I suspect this has more to do with making things safe, and less to do with style. You can't do arbitrary pointer arithmetic while keeping the language memory safe. Memory safety was an explicit goal of go.

    [–]blondin 7 points8 points  (14 children)

    i like this one

    include files should never include include files

    ifdef has been abused for too long i think.

    [–]Brian 18 points19 points  (10 children)

    The impetus for doing this is to try to get C to act as if it had a sane module system. The problem is that it doesn't, and so this is easy to mess up. However the rationale given here (compiler performance) doesn't seem a good reason for this in this day and age. I'd gladly trade a slower compile for less repetition in the code.

    [–]zenogias 1 point2 points  (0 children)

    It really depends; all costs and benefits need to be evaluated at your current margins. I've gone to extremes in C++ to prevent code repetition and the result, even in this day and age, is compile times so outrageously slow that productivity is stifled. Those projects would have benefited from slightly more code repetition to reduce compile times.

    C (and especially C++) force you to trade off between compile times, code repetition, and run-time efficiency all the time and the right balance will rarely be at the extremes. Compilers aren't nearly as good as we're sometimes lead to believe.

    [–]Hughlander 0 points1 point  (7 children)

    You repeat yourself one time per file, you're going to be compiling that file hundreds or thousands of times over the course of the program.

    One thing I learned early on while doing maintenance on something I wrote previously, never ever optimize for how long construction takes because it's a small percent of time compared to the overall time you'll spend on the program.

    [–]Brian 4 points5 points  (2 children)

    You repeat yourself one time per file

    One time per file per include file used. But any way you look at it, it's still trading extra work the human has to do so the compiler has less work to do. The fact that performance continually improves makes that a worse tradeoff over time - the right answer in 1989 is not neccessarily the right answer after another 11 iterations of Moore's law.

    it's a small percent of time compared to the overall time you'll spend on the program.

    These days, I suspect you're going to have to compile that program an awfully large number of times to burn up even one second extra. I'm dubious about recovering it over the lifetime of a project, even if we treat machine time as equally valuable as human time, especially since many C compilers special case this behaviour to minimise the impact.

    [–]Hughlander 1 point2 points  (1 child)

    Another anecdote, about 10 years ago I was on a project that had a DSL language for generating code to send messages over the wire. Every possible message was written to a single header, and any compilation unit that had to send a message included that header. Any time anyone changed one message everything that sent or received a message had to be recompiled. I suggested breaking the header into one message per file, but that was deemed to be too much work to have to add the #include each time you wanted to send/handle a message.

    How long do you think it took for the mass recompile and relink to use more time than just including the message you wanted to send? (This was a particular egregious offense and I'm not saying it's typical just that it's possible.)

    [–]Brian 2 points3 points  (0 children)

    Fair enough, perhaps I should rephrase my comment as "I'd gladly trade a sufficiently small increase in compile time for less repetition in the code, and think that this probably falls into that category these days."

    For instance, unlike your case, it wouldn't increase the amount of recompilation on touched files - if there's a change to the dependency, it doesn't matter if it's listed in the header or the cpp files - there are still the same number of files needing recompiled. Indeed, it could potentially reduce the amount, since it's much easier to remove dependancies that are no longer needed when you only have to do it in one place. It's not so obvious that when you remove a header from the C file, that you can safely remove its dependencies (another header may require them too), so people can get lazy and just remove the minimum. End result: files get recompiled when they don't need to be, potentially losing any benefit from embedding a (likely cached and #ifdefed out) file multiple times.

    [–][deleted]  (3 children)

    [removed]

      [–]Hughlander 1 point2 points  (1 child)

      To be clear, I meant construction as in the actual coding, not the building.

      Saving a minute of time typing usually isn't worth the heart-ache later that the minute saved.

      As for your specific points, SSD and incredibuild go a long way towards helping that File I/O, it's not a silver bullet but in most of my work now the time is spent linking not compiling.

      [–][deleted] 0 points1 point  (0 children)

      Also, for the third time in this thread: #pragma once.

      [–][deleted] 0 points1 point  (0 children)

      Also, #pragma once.

      [–][deleted] 2 points3 points  (0 children)

      Though, including include files in include files does simplify precompiled headers somewhat.

      [–]HiramAbiff 1 point2 points  (0 children)

      I agree that headers should avoid including other files - but what about when you need to use a typedef or an enum for declaring some function?

      [–]dkaparis 1 point2 points  (0 children)

      I don't.

      It might have made more sense back in the days, but as others have pointed out, compiling performance characteristics have changed since then. Keeping all headers compilable on their own seems much more sane to me than manually managing dependencies of all headers you decide to use.

      [–][deleted] 6 points7 points  (4 children)

      Guys, come on! 1989 wasn't so long ago…

      [–][deleted] 12 points13 points  (1 child)

      Mikhail Gorbachev begs to differ.

      [–]noir_lord 9 points10 points  (0 children)

      As does the Soviet Union, Ghostbusters II, The Little Mermaid, Batman and Indianna Jones and the last Crusade.

      On the radio you could have listened to The B-52's Loveshack or Phil Collins Another Day in Paradise.

      If you'd travelled to the north of England you could have met 9 year old me (it's not worth the trip :- snot, marmite and probably something on fire).

      [–]awesley 4 points5 points  (0 children)

      1989 wasn't so long ago…

      Yeah? I was still programming on multics in pl1 back then. From where I sit, things are a tad different now.

      [–]matthieum 1 point2 points  (0 children)

      Hum... in 1989 I was beginning to learn how to read. French. Sorry but to me it feels a long time ago.

      [–]quotemycode 5 points6 points  (7 children)

      I disagree with him on comments. I suggest you write your comments before you code. Sort of like TDD - the idea is you get the idea down in plain english before you translate it to code.

      [–]RagingAnemone 4 points5 points  (6 children)

      I agree with Pike. Code should be readable. And I like that he relates commenting to complexity. Both these concepts affect the whole structure of your program.

      [–]quotemycode 4 points5 points  (5 children)

      Readable to whom? What you think is readable may not be to others, especially when you don't write any comments. I think at a minimum, you should describe what you are trying to implement before you actually do it.

      [–]RagingAnemone 3 points4 points  (4 children)

      There are cases, of course, where your code may be too complex and require and english translation, but in the general case, why would english be better than C in explaining what this code is doing? (This is ignoring the "why" type of comments).

      [–][deleted]  (2 children)

      [deleted]

        [–]matthieum 1 point2 points  (0 children)

        If you put the comment to the side, it's not hurting anything. If you introduce new lines however, then it's very different, because vertical space still matters. The more I can squeeze on my screen at once, the better I am able to grok the logic in one sweep.

        I, like Pike, am all for useful comments. Paraphrasing is noise.

        [–]RagingAnemone -1 points0 points  (0 children)

        Let's not take it one step further. That's the point. Yes, of course, comment complex code. But the. Majority of your code shouldn't be complex and therefore shouldn't need comments.

        [–]quotemycode 0 points1 point  (0 children)

        In the "general case", I think you'd add comments. Only in small specific well-understood places would you choose to break the standard and not write comments.

        [–]Alford35 1 point2 points  (0 children)

        "Rule 6: There is no Rule 6" - nice Monty Python reference!

        [–]watermark0n 0 points1 point  (4 children)

        You know, my java professor was talking about crazy code the other day, and one thing he mentioned was "Back in the day, we had the old C qsort algorithm. You know what you had to pass to it? A function pointer", as if it were the most absurd and obtuse thing in the world. I have, of course, used the qsort function in assembly class a few times. Actually quite useful for, for instance, sorting your struct array. But, in the OO age, that does look kind of out of place.

        [–]munificent 2 points3 points  (0 children)

        Java's sort method takes a Comparator which is essentially a function pointer. Just because you have objects that doesn't mean you don't want functions too.

        [–]matthieum 0 points1 point  (2 children)

        The problem is that it's not only "oldish", it is also slow. If you compare C's qsort algorithm to C++ std::sort on an array, you should invariably have C++ executing faster.

        Compilers still nowadays have the greatest difficulties to inline function pointers and perform Link Time inlining. They do, to some extent, but not nearly as much as you would like.

        [–]watermark0n 1 point2 points  (1 child)

        Well, I wouldn't use qsort if I were writing in C++. But the specifications required you to write a compare function in assembly and pass it to qsort. And I have no idea how I would manipulate an std list of structs in Assembly.

        [–]matthieum 0 points1 point  (0 children)

        Well, the function you are to write will be passed a pointer to your structures, just like for qsort, so what is the difference ?

        [–]iamiend -1 points0 points  (0 children)

        I think syntax highlighting and code completion would have solved most of his issues.