
Deep C and C++ (2011) - kamaal
http://www.slideshare.net/olvemaudal/deep-c
======
hacknat
I'm not so jaded as to think that deep language understanding isn't a useful
or good thing, and I'd like to think I have some myself. However, deep
language understanding is not what separates the great engineers from the good
ones.

In an interview, I would much rather hear a person say something about a
statically declared variable with no initialization being poor code to leave
behind for the next person than some arcana about the standard.

~~~
ksk
>In an interview, I would much rather hear a person say something about a
statically declared variable with no initialization being poor code to leave
behind for the next person than some arcana about the standard.

Why are you forcing those two choices? One could be well-versed with the
arcana AS WELL AS point out that bit about statically declared variable ..

The problem IMO is most programmers cargo-cult/copy-paste/stackoverflow their
way into programming jobs. No, that does not mean you never ask for help. No,
that does not mean you never copy-paste. (Phew!)

Its sort of like when you're learning math. Great mathematicians can
understand the theory and just apply it to whatever problem they come across.
Its because they have a very solid foundation underneath them. They wield
their knowledge like tools and can just build anything with those tools
because they understand those tools very well. Most students however just
learn the patterns of the problems. And once they know enough patterns they
can solve problems which fit into one of those pre-understood patterns.

The people who are deeply knowledgeable about the language are good at knowing
the boundaries of the language, knowing when you're using constructs that are
not valid-syntax (which still compile), etc. The social aspect of 'good
comments' , 'readable code' or 'maintainable code' is _also_ important. You
can have programmers that do both. Ofcource those programmers will never work
for 'you' (not you, personally..) because most programming jobs are shitty and
do not require programmers of that skill. You'll find them toiling away in
anonymity, working in research labs, working on compiler optimizers or
operating systems or some other domain with challenging technical problems.

~~~
cousin_it
> _Great mathematicians can understand the theory and just apply it to
> whatever problem they come across._

As someone who's both a mathematician and a programmer, I think that analogy
glosses over an important difference, which is also relevant to why many
people refuse to memorize certain things.

Good mathematical theories are internally consistent in a very strong sense.
When you're learning them, you feel like you're learning something eternal
that could not possibly turn out any other way. If you forget half of
calculus, you can reconstruct it from the other half, and the reconstruction
will be unique.

The details of programming languages, like C and especially C++, are not like
that. For many mathematicians who would otherwise make excellent programmers,
the details of C will feel like something not worth memorizing, because they
don't make sense - they are not an inevitable, provably unique solution to any
problem.

To a mathematically inclined mind, programming concepts form a hierarchy
depending on how "inevitable" and worth memorizing they are. Concepts like
computability, lambda calculus or big-O complexity are near the top, syntaxes
of specific languages are lower down, and API details are at the bottom. That
also reflects the rates of change: math doesn't change, languages change every
decade, and APIs change every year.

If I want to hire a programmer for the long term, as opposed to getting quick
help on my current project, I will be mostly asking them about concepts from
the top of the hierarchy, not what static means in C. Of course some people
will disagree with me and demand detailed knowledge about static or templates
or whatnot, while dismissing mathematical questions as "puzzles". Maybe that's
also a valid style of programming, I'm not sure...

~~~
ksk
No, I too am talking about a hierarchy of internally consistent knowledge.

Have you implemented a compiler or a interpreter for a popular language? I
could be wrong but I strongly suspect you haven't. If you have ever
implemented a compiler you understand the language at a fundamental level and
when stumped with a bug or a highly technical puzzle or what have you - you
get that "aha" moment where its like "Ofcource ! How else could it be. This
language feature must be using this construct because of X or Y reason and the
compiler has to work this way because this part here doesnt allow for it to
work any other way, etc ,etc and the optimizer has xyz amount of scratch
registers so abc condition could never happen, and on and on."

~~~
cousin_it
My comment was talking about a stronger kind of consistency, maybe
"inevitability" would be a better word for it. You could make many different
tiny changes to the rules of C and still end up with a workable programming
language. (Many people have done that, there are tons of languages derived
from C.) You could say that the rules of C are "random" \- after learning the
first n rules, you cannot use logic to predict the n+1st. So learning the
rules of C is more about memorization than logic. Math is different: when you
learn a piece of math, you know exactly how it follows logically from the
pieces you learned before, and you know it couldn't be any other way. That's
why it feels more reasonable to me to inquire about math, rather than the
details of C.

Lawrence Kesteloot said it well at
[http://www.teamten.com/lawrence/writings/what_interests_me.h...](http://www.teamten.com/lawrence/writings/what_interests_me.html):

 _On a planet far away they have universities. In those universities they have
many of the same subjects we teach here, such as math, biology, philosophy,
history, computer science, psychology, and literature. But although the
subjects of the classes are the same, the contents are different. They teach a
history class, but their history is different from ours. So are their biology
and literature. I’m not interested in subjects where their content is
different from ours._

 _In some classes, though, the content is the same. They’re teaching the same
physics class (assuming they’re at the same level of understanding we’re at)
and the same math classes (with a different base). In computer science most of
what they teach is different, but their theory of computation is surely the
same. Their biology is different, but their teaching of evolution is the same.
Their philosophy is vastly different (think how different Eastern and Western
philosophies are on earth), but their philosophy of science is probably very
similar._

Even if this point of view doesn't make sense to some people, I subscribe to
it because it's very inspiring to me. YMMV.

~~~
ksk
>You could say that the rules of C are "random" \- after learning the first n
rules, you cannot use logic to predict the n+1st.

You're mis-applying things here. The language is not something to be theorized
by itself. Like any (edit:spell) other body of knowledge, it has its own set
of initial axioms and the 'C standard' which defines the language is simply a
collection of rules other meta-knowledge which are based on those. In that
sense it is internally consistent. Thats what I meant.

~~~
cousin_it
Yes, you could say that the C standard is a formal theory. It won't be a very
interesting one to a mathematician though, because it's huge and describes
only one thing, C. There are no special considerations to single out that
theory from a huge pool of similar ones. It's like devoting your life to the
study of one particular differential equation with a thousand terms, which was
written by a committee. Why not the other equation which has a minus instead
of a plus over there? Why not study differential equations in general?

Compare with a formal theory like PA, which fits on a page and describes the
natural numbers. Proving a theorem about PA has implications everywhere,
because natural numbers are everywhere. Or if we want to talk about
computation, there are many formal theories with short descriptions that have
much more to say about computation in general.

~~~
ksk
I am not against your POV ! I think we largely agree on most things here. I
wanted to correct what I perceived to be a mischaracterization of my 'off the
cuff' analogy.

~~~
cousin_it
Yeah, from your reply to patrickmclaren I understood the point you were trying
to make, and I agree with you. Sorry for misunderstanding you so persistently.

------
agentultra
I love this presentation. It led me to read _Expert C Programming_ [1] by
Peter Van Der Linden. My knowledge of C had vastly improved after reading that
book (and subsequently C++). Even if you're not a C programmer I would
recommend the book as the anecdotes alone are worth reading for the questions
that it encourages you to ask.

I've since come to believe that reading the specifications and having the
attention necessary to delve into these kinds of details and ask the _right_
questions is important for mastery. It seems to me that learning 1 - 2
languages to this level of detail is worthwhile. I've been thinking of cutting
back the number of languages I, "know," down to just those for which I am
familiar with the specifications and how they're compiled, assembled, etc.
Everything else is superficial.

Sometimes all you need is just a cursory knowledge to get something done and
the ends justify those means. However if you really love your craft then
mastery should be the goal, no? It seems to be the difference between,
"getting something working," and, "pushing the boundaries of what is
possible."

[1] [http://www.amazon.ca/Expert-Programming-Peter-van-
Linden/dp/...](http://www.amazon.ca/Expert-Programming-Peter-van-
Linden/dp/0131774298)

~~~
NAFV_P
"C programming is a craft that takes years to perfect. A reasonably sharp
person can learn the basics of C quite quickly. But it takes much longer to
master the nuances of the language and to write enough programs, and enough
different programs, to become an expert. In natural language terms, this is
the difference between being able to order a cup of coffee in Paris, and (on
the Metro) being able to tell a native Parisienne where to get off." The
behaviour of this quote from the beginning of Linden's book is, strictly
speaking, undefined. I interpreted it as being able to give instructions to a
native Parisian, in order to find the nearest red-light district.

~~~
kenko
"where to get off" has at least three interpretations---the one you note, one
in which you insulte the Parisienne (why a Parisienne? Why not the English
word, which has the advantage of being gender-neutral, "Parisian"?), and the
(presumably) intended interpretation, what exit to use.

~~~
NAFV_P
"why a Parisienne? Why not the English word, which has the advantage of being
gender-neutral, "Parisian"?" I believe I did use the term Parisian.... I could
have used the even more offensive (joke) term "parisite".

------
nraynaud
this has nothing to do with understanding but more with memory. What's
drowning people in C and even more in C++ is not the logic of the language,
but the sheer number of tricky concepts and the pure accumulation of
information (it is reflected on the size of the specs).

There is also the fact that very often non-specified behavior, or
implementation dependent or everything else that is not cool does not lead to
a warning, so the learning is absolutely not reinforced by the compiler.
Whereas a warning/error leads to questions that leads to google and some
learning; you can be stepping far in the Pampa of undefined behavior for years
when someone comes with a superior attitude in your company detects it and
calls you a moron in a powerpoint.

And this also leads to very hard to write code sometimes, if you want to do
some serious IEEE754 in C/C++ you will basically be pitting the spec of the
language against the spec of numerical computation in a ring.

~~~
kyllo
_What 's drowning people in C and even more in C++ is not the logic of the
language, but the sheer number of tricky concepts and the pure accumulation of
information (it is reflected on the size of the specs)._

I agree, and I'd add that C/C++ is a bit of a leaky abstraction layer over
assembly. It aims to be portable, but true portability means that the C/C++
developer really shouldn't have to know/care what assembly instructions the
compiler/linker is emitting, because all of that stuff depends on which chip
architecture you're targeting.

Basically, coding in C/C++ requires an intimate knowledge of how the compiler
works, and sometimes even how the target chip works. C/C++ software projects
of notable size oftentimes cannot be simply recompiled/linked to a different
target architecture without changing things like compiler flags, the makefile,
and even the application code itself. That makes it a non-portable, leaky
abstraction, and dramatically increases the amount of knowledge that's
required of a C/C++ developer.

~~~
bjackman
I've been spending a lot of time recently looking into and thinking about
alternatives to C.

I'd love to see a language as close to assembly as C is, but with a cleaner
disconnect with it. As an example of what I mean:

Bitfields would be really handy when writing a device driver. A basic example
of the difference they would make is "if (reg.field == VAL)" vs. either "if
(reg & MASK == VAL)" or "if (GET_FIELD(reg) == MASK)". But you can't use them
for that purpose because their layout is implementation defined.

There would be a noteworthy performance benefit to pay for portable bitfields,
but I think it would be worth it. Right now I have to write ugly code if I
want any attempt at portability (always). I'd much rather have to write ugly
code where I need speed (sometimes).

I'd love to hear if anyone else has any ideas on this matter (BTW it seems
like D solves many of the problems I've been thinking about, but it's memory
managed).

------
praptak
A fun fact about sequence points. C++ has switched from "sequence points" to
"sequenced before/sequenced after" relation. And it is not really "all"
previous side-effects that are guaranteed to be visible after the sequence
point but only those associated with the sequence point.

In 'foo(b++, a++ && (a+b));' the sequence point introduced by the '&&' only
makes the 'a' see the effect 'a++' but the 'b' might not see the 'b++'
(function args are not sequenced in C nor C++).

~~~
coldpie
Why on Earth are you writing a statement like that in the first place?

~~~
praptak
Exaggerated example to show a pattern. A (hopefully) less outrageous (but
still bad!) example of the dangers of sequencing:

    
    
        foo(std::unique_ptr<T1>{new T1 },
            std::unique_ptr<T2>{new T2 }); 
    

This one's from GotW #102.

~~~
alok-g
Thanks. Just read the GotW.

[http://herbsutter.com/gotw/_102/](http://herbsutter.com/gotw/_102/)

------
raverbashing
It's a good discussion of the behind the curtains working of compilers

But I'm very aware of "smart code" and we shouldn't be writing code that
relies on the details (especially ones that might change between compilers)

~~~
greyfade
But we should certainly be aware both of what the language requires of the
compiler and of potential pitfalls.

~~~
waps
The problem there is that while compilers have been getting better, they're
nowhere near beating good programmers (yet ?). Languages other than C/C++ get
in the programmer's way and prevent them from using "maximum" cleverness, and
that means the best java/c# programs are simply always going to be slower than
the best c/c++ programs.

~~~
dllthomas
That's true on balance, which is why C/C++ is still typically faster than
managed languages. In many particular cases it's not true, however. Consider
"register" or "inline" directives, which have been advisory for a long time.

------
loup-vaillant
This was good, but…

Hermione (I'm sure that's her) rates her C++ knowledge at 4-5, and Stroustrup
himself at 7!?

Bullshit. Either they are poorly calibrated, or they are displaying false
modesty. Sure, they probably still have plenty to learn about C++, but come
on, Hermione is already at the top 97% in terms of language lawyering.

Wanting to be stronger is good. Not realizing you're already quite strong is
not so good.

~~~
svantana
It's real, it's called the Dunning-Kruger Effect. I've seen it plenty of times
with real superstar-experts rate themselves as "slightly above average"...

[http://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect](http://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect)

~~~
RogerL
I think it is more than that. I had a boss that basically would not hire
somebody if they said they were at the top of any measure. In one sense, she
was correct. No one can know everything about C++. OTOH, if you are in the 9x
percentile, why should you not rate yourself at 9-10 out of ten? At some point
it gets silly when you are arguing about how you should properly distribute
yourself in bins so long as you understand the scope of the problem.

~~~
okamiueru
The only problem with that is that you have no way of knowing what kind of
scale adjustments they are using.

[http://hyperboleandahalf.blogspot.no/2010/02/boyfriend-
doesn...](http://hyperboleandahalf.blogspot.no/2010/02/boyfriend-doesnt-have-
ebola-probably.html)

------
chipsy
People complain loudly about gotchas in JS, but when you look at what C++
programmers have to contend with...

~~~
hamidr
At least C++(11) is a (better) statically typed language :) Although, This
isn't even half of it! thanks god the girl didn't know anything about
templates.

~~~
dllthomas
Templates are a horrid syntax for an okay functional, compile-time language.
They can be useful - in quite a few ways an improvement on C macros. I say
this as someone who's done quite a bit of C and C++, and am currently working
mostly happily in C at work and Haskell on my side project.

------
theCricketer
A college student in CS here. I'm always impressed by people with deep
understanding of programming language internals and try to pick up as much
about programming language internal workings and compilers as I can. How does
one get really good at this? Is it by spending a lot of time programming and
building stuff? Is it by reading books/blogs/articles about programming
languages? Any recommendations for such resources?

~~~
pjungwir
Everyone else's advice to learn by doing is great, but there is also _Expert C
Programming_ by Peter van der Linden:

[http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp...](http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp/0131774298)

The presentation's "Deep C" pun is a reference to this book, and if you make
it all the way to slide 444 you'll see it mentioned as further reading. It's a
wonderful book for understanding C (not C++) and what's really going on.

~~~
bloodorange
It'll take a team of ten authors and a couple of decades to write something of
that kind for C++.

Though the language is full of horrors, I still quite enjoy C++ (esp. with
C++11 and am looking forward to some C++14 features...)

~~~
qznc
I know at least one guy, who is on it.
[http://herbsutter.com/gotw/](http://herbsutter.com/gotw/)

~~~
bloodorange
Nice! Thanks for the link.

------
kirab
I got really annoyed by those stupid and ever-repeating mean comments like "do
you want another ice cream?"

~~~
mrottenkolber
I also found this very awkward. Especially because the author created the
character he subsequently demolished.

While I can follow most of the C problems, C++ has never interested me. As as
a Common Lisp programmer, all of this seems quite demented. By reading the
slides I have learned about some interesting optimization concepts, and
wondered how CL compilers do it. But honestly for 99% of my Job I couldn't
imagine using something like C.

Edit:grammar.

------
jgreen10
How far into the presentation do I need to go for someone to mention that the
quotes in the printf are not US ASCII and therefore the program would not
compile?

------
pacaro
I've been a C developer (among other things) for about 20 years or so, but
I've always described my C++ skills as being "in the C with objects" range, I
might have to change that to being "nearly in the C with objects" range.

~~~
jgreen10
I didn't have any trouble with the C examples, but with C++ it just puzzles me
why people would want to use a language like that in the first place. What
does it buy you except bigger head aches?

~~~
dman
RAII.

~~~
jgreen10
You don't need RAII if you don't have exceptions. Separating allocation and
initialization is a good thing.

~~~
dman
RAII is used for idiomatic cleanup from a function. In C the way to handle
that would be to have a cleanup section in every function and then doing a
goto to that which adds clutter to the function.

------
rcfox
Previous discussion:
[https://news.ycombinator.com/item?id=3093323](https://news.ycombinator.com/item?id=3093323)

------
yngccc
The girl forgot to mention exception safety on the class A slide, no hire.

~~~
jmgao
The constructor also wasn't tagged explicit.

------
revelation
What bizarre nonsense. I hope nobody thinks this level of (mis)understanding
is replacement for understanding, you know, how to _program_.

The majority of this is undefined behavior or implementation details of your
compiler. If you rely on that, I don't want your code anywhere near my
machine.

~~~
pkolaczk
I think you missed the point. It is more about coder's attitude than about
using (or not using) the presented examples in real code. I wouldn't like to
work with a programmer than writes shitty code accidentally relying on UB, and
denies every criticism by saying "it works, so what's up?".

------
Suncho
Most of the C stuff here is pretty good, but some of the C++ information is a
little questionable. Even the "good programmer" exhibits a few common
misconceptions about inheritance and virtual destructors. Here's the text from
slide 348:

"What is the point of having a virtual destructor on a class like this? There
are no virtual functions so it does not make sense to inherit from it. I know
that there are programmers who do inherit from non-virtual classes, but I
suspect they have misunderstood a key concept of object orientation. I suggest
you remove the virtual specifier from the destructor, it indicates that the
class is designed to be used as a base class - while it obviously is not."

She's right that the class described on the slide probably shouldn't have a
virtual destructor.

 _A base class should have a virtual destructor if and only if objects of its
derived class are to be deleted through base class pointers._

The following four statements are wrong:

1\. A class with other virtual functions should have a virtual destructor.

2\. A class without other virtual functions should not have a virtual
destructor.

3\. A class designed to be a base class should have a virtual destructor.

4\. You shouldn't inherit from classes that don't have virtual functions.

It's a narrow-minded to say that programmers who inherit from "non-virtual"
classes have "misunderstood a key concept of object orientation." Which key
concept is that, by the way? Object orientation isn't the be all and end all
of C++. There are reasons to use inheritance that have nothing to do with run-
time polymorphism. Maybe you just want to reduce redundancy and organize your
data types in terms of each other.

Another gripe is that on slide 369, she says:

"When I see bald pointers in C++ it is usually a bad sign."

Naked pointers should usually be avoided for memory management. That's true.
But they make great iterators, and they're useful, along with references, for
passing objects to functions.

On the other hand, seeing the keywords "new" and "delete" in code is usually a
bad sign. Resources (not just memory) should be managed by resource management
classes. If you try to do it manually, especially in the presence of
exceptions and concurrency, it's very easy to cause an inadvertent resource
leak.

~~~
NAFV_P
"On the other hand, seeing the keywords "new" and "delete" in code is usually
a bad sign." I thought those two keywords were intended to replace the basic
memory allocation functions found in stdlib.h. What are the alternatives?

~~~
Suncho
As other folks have mentioned, unique_ptr, make_unique, and all their happy
friends are there if you need them. But your variables/objects should go on
the stack unless you have a reason not to put them there. As the slide
suggests, if you need a lot of stuff on the heap, a standard std::vector will
often do.

In C, it can be tricky to ensure that every _malloc_ has a matching _free_ and
every _fopen_ has a matching _fclose_ etc. This style of resource management
is error-prone, but it comes with the C territory.

Java throws its hands up in the air in disgust and basically accepts that you
will generate a lot of garbage. Then it slaps a mandatory garbage collector on
top to clean everything up, which I guess is an okay way to deal with memory,
but it sucks for other resources that aren't managed by the garbage collector.

C++, on the other hand, makes it easy to write garbage-free code. But it's
only easy if you avoid using _new_ or similar functions that allocate
resources such as file descriptors, locks, network sockets etc.

If you see people using "new", there's a good chance they're misguided C or
Java programmers.

C programmers often think they should use _new /delete_ as often as they used
_malloc /free_ in C. Java programmers sometimes try to use _new_ every time
they instantiate an object. Java did steal the _new_ keyword from C++, and
it's perfectly normal for Java code to be riddled with _new_ 's because
there's no other way to do it in Java. But these styles lead to disaster in
C++.

------
zvrba
> Why do professional programmers write code like this?

Because we 1) for some reason or another we _must_ use C or C++, 2) we're
coding for a single CPU platform, and 3) we need to get the friggin' job done
in this century.

------
chr13
I haven't seen these tricks come into play when solving real problems at ALL.
Not saying you should not know the language, but better to have problem-
solving skills than rot the standard. The bit about leaving a new line after
main tells me she really has memorized the standard.

~~~
dllthomas
It's not about tricks, it's about precisely understanding the mechanics of the
language. This can be exploited to craft tricks, which is occasionally
important. It can also be exploited to avoid gotchas, which is usually
important. It can also be exploited to better and more quickly understand what
some behavior means when things aren't working as expected, which is always
important.

~~~
chr13
I guess it depends on what you consider "real problems". One can always write
good and efficient code by following what he/she knows is the defined
behavior. Just found weird that some things related to standards were given
more importance whereas problem solving is the key while writing any program.

~~~
dllthomas
Well, I'm currently being paid to write C day to day, so it's solving
someone's real-enough problem that they're willing to part with money. I
described roughly how I see my comprehension of the language reflected in my
work.

~~~
chr13
So am I and I've mostly used a subset of C features to solve many problems.
I've also seen some C 'experts' fail to come to a proper solution even if they
know all the features.

~~~
dllthomas
_" I've mostly used a subset of C features to solve many problems."_

Sure. What about code written by others? What about when you're debugging and
something just isn't working the way you expect because you've unknowingly
stepped outside that subset? (Most of the important concepts here aren't
syntactic constructions you can avoid trivially by typing Y instead of X, and
may or may not be detectable statically). Also, maybe you're missing
opportunities to better insure your code is correct at compile time - I'm not
sure whether it falls within your subset, but for instance I recently put
together a macro that asserts statically that two expressions have the same
type (and without any runtime cost).

 _" I've also seen some C 'experts' fail to come to a proper solution even if
they know all the features."_

Obviously. Knowledge of the spec and your compiler aren't the _only_ thing
that matter, by a long shot. I'm just saying they most emphatically _are_
helpful.

~~~
chr13
I guess you summed it up. Indeed having more depth in a language is very
important and useful, I was just trying to make a point that these aren't the
only things. Here is how I perceive a language,

It is made up of syntax and behaves in a certain way. If you read the
documented features you'll know all of it. There may be some undocumented
things which may not be of utmost importance. However, this is just the base
of programming. And when you start dealing with 5-6 languages you _can_ forget
things if you don't have a good memory but the good thing is it's all
documented and _known_ features. Whereas while programming, one can often be
involved in solving _unknown_ problems, which can't be figured out just by
googling.

------
deckiedan
It is interesting looking at the 'deep' issues of programming languages. This
kind of ties in with the "Don't ask me maths questions..." post a few days
ago.

There really is a lot more to programming than just algorithms, UI design or
syntax.

~~~
raverbashing
Yes, this worries me.

Especially today some people think "great programmers" are the ones who knows
all the "fashionable" tools and frameworks, wants to abstract everything (god
help him if he install vim in his test environment without a fab file that
configures chef) and maybe worships Uncle Bob

Knowing how to use Redis is cool, do you know what's even cooler? Being able
to write it (or at least knowing how it works more or less)

~~~
dmak
I'll rather pay an artist to paint me a nice piece using store bought paint
than making his/her own paint.

Each programmer is great in their own right.

~~~
EliRivers
_Each programmer is great in their own right._

Some of them, however, are terrible at programming.

------
glormph
I only know python well and am looking for another language to learn. C was on
the shortlist, but after this, crikey. At least I now know it's not going to
be an easy ride.

~~~
userulluipeste
I found the original ANSI C to be more straightforward, and many times after I
was asking myself "why was this done in this way" I only realized that I would
have ended up with the same way of doing things - e.g. that the stack arrays
should just skip the "pointing" memory, and things like that. What you saw in
the presentation are mostly just later complications that popped up from the
attempt to improve the manner of approach while keeping the entire thing
speedy and backward-compatible. Do you think this is too much? Take a look at
C++11 and marvel at the quantity of language hacks there!

------
rfv
I wonder what a linux kernel developer would have to say about these slides.
How many of these features/quirks are they finding useful in their day to day
job.

------
aidenn0
Heh, and they didn't even get into the aliasing rules. In embedded software,
life would be a lot easier if I could hit every engineer who wants to type-pun
without a union in the head with the ISO standard.

For this reason, a lot of compilers have options to not strictly enforce the
aliasing rules

[edit] Also C and C++ are both permitted to reorder structs, it's just that
they don't because that's the easiest way to follow the standard.

~~~
jmgao
As mentioned by others, C does not allow reordering of members in structs.
However, C++ does!

§9.2.12 says:

    
    
        Nonstatic data members of a (non-union) class declared without an
        intervening access-specifier are allocated so that later members
        have higher addresses within a class object. The order of allocation
        of nonstatic data members separated by an access-specifier is unspecified (11.1)
    

This means, that under a strict reading, even the following struct can have
its members reordered:

    
    
        struct foo {
            int a;
        public:
            int b;
        }

~~~
ben0x539
Did this change in C++11 or does this wording mean the same thing? It's not
clear to me that the implicitly public a is of a different access control than
the explicitly public b according to the following wording:

> Nonstatic data members of a (non-union) class with the same access control
> (Clause 11) are allocated so that later members have higher addresses within
> a class object. The order of allocation of non-static data members with
> different access control is unspecified (11).

------
brohee
The girl spewing some bullshit may lead to an interview ended early. Clearly
bright, but not as bright as she think she actually is... Come back in a few
years with a bit more humility... Hard to decide if the other guy is bad or
inexperienced without a resume...

"If you compile in debug mode the runtime might try to be helpful and memset
your stack memory to 0"

This is a retarded explanation (pages are set to 0 when they are recycled by
the OS so you don't end up having data from dead processes mapped in your
memory, with all the security implications). Also, actually randomizing memory
in a debug context would actually be more helpful to trigger those
initialization bugs...

People that think they know everything are a lot more dangerous than people
actually aware of their limitation and safely working within them.

~~~
RogerL
Okay, you are assuming an Intel architecture? Plenty of embedded environments
don't have OSes, let alone pages or virtual memory.

IOW, I've worked in environments where, yes, the value in memory is based on
what the compiler does in debug mode, not what the OS might be doing. I'd say
the girl's answer is, while not exhaustive, certainly correct. Without more
context, we don't know why the value was 0.

~~~
brohee
You have printf, and the interviewer says "on my machine, I actually get 1,
then 2, then 3". Those two hint very strongly at a general purpose computer,
thus paging etc.

What really annoyed me is the suggestion that zeroing is more helpful than
randomization in a debug context. Randomizing everything not defined by the
standard is a good way to trigger lots of bugs based on false assumptions...

~~~
dllthomas
There are two legitimate concerns in a debug context. The first is
predictability / repeatability; zeroing is substantially more helpful than
randomization in this context.

The second is revealing incorrect assumptions / fuzzing / stress testing;
zeroing is substantially less helpful than randomization in this context.

Ideally, both options would be available. When someone says "give me a debug
build", I think it's probably correct that they are caring more about the
former, but really it should be clear and controllable.

~~~
brohee
Predictability and randomization are not mutually exclusive, you only need a
way to specify the seed for the PRNG used during randomization.

~~~
dllthomas
No, that addresses reproducibility, which is worthwhile but is not the same as
predictability.

Predictability in this context means simplifying the problem. If uninitialized
memory is nulled, then I know what I'm looking for/at more quickly. Likewise
if it's set to any other particular, known value. I know it will (or won't) be
failing null checks, and I know that it will (or won't) be segfaulting if
dereferenced. This helps with characterizing and fixing bugs, (related to but
distinct from detecting bugs in the first place). Relying on this to make the
program work is bad, but that's not the same thing.

------
dllthomas
I'm not sure "provide only one way of doing things" is a core principle of C.
It at least seems to have fallen to "type less" in several cases:

    
    
        i = i + 1;
        i += 1;
        i++;
        ++i;
    
        a[i]
        *(a + i)
    
        a->foo
        (*a).foo

~~~
humanrebar
You left out: i[a]

~~~
dllthomas
I considered it, but decided it would be more noise than substance in this
particular list. I do like that pun, though.

------
NAFV_P
I signed up with HN to get articles related to C, yet they're about as common
as hens teeth. I've just executed a word search on this comments page: 18
instances of "static", but no mention of "volatile" or "extern", which is the
same situation in several textbooks on C. The article mentioned looking at the
assembler output of a program, but didn't give any hints on where to learn
some assembly.

~~~
xradionut
You need to learn the history of HN and realize that Lisp is the original
hacker language.

As for assembly, there's been several lists of "free" computer books post that
have included assembly tutorials.

~~~
NAFV_P
"You need to learn the history of HN and realize that Lisp is the original
hacker language." That's fairly common knowledge, I've been coding for
eighteen months and I learned that "fact" months ago. "As for assembly,
there's been several lists of "free" computer books post that have included
assembly tutorials." I haven't mentioned what assembly I wish to learn. A lot
of the assembly tutorials I have found on the web talk about x86 assembly, yet
my processor is 64-bit. I'm quite sure that the principles extend easily from
one register size to another, but I have no experience at all in assembly.

~~~
blt
I would recommend the CS 61C course videos from Berkeley:
[http://www.youtube.com/playlist?list=PL01C2A0DE46A54CA9](http://www.youtube.com/playlist?list=PL01C2A0DE46A54CA9)

It uses MIPS assembly, which you can run on a simulator. I don't think many
machine architecture classes teach x86 because it's more complex. The MIPS
knowledge from that course has translated easily to x86 in my tiny experience
of peering into my compiler's assembly output.

------
jheriko
seen this before. whilst its great there are degrees of respect to have for C
and C++.

the most productive code i have ever written generally involves me working
around the constraints of the language to implement a paradigm which is
missing at compile-time, or juggling macros and templates so that i can reduce
boilerplate code down to a template with a macro to fill the gaps the template
is too featureless to give me (vice versa, the template is there because
macros aren't complete enough either).

its good to understand this deep language stuff though because you can
understand why C/C++ are limited. for instance the C sequence points limit the
compiler in its ability to perform optimisation, as do struct layout rules and
many of the other weird and wonderful specifics...

what saddens me most though is that nobody has offered anything to improve C
and C++ in these areas which matter most to me... its not even hard. just let
the compiler order structs because most programmers don't understand struct
layout rules.

its not a good thing that these things are so explicitly specified for the
language - its gimping the compilers, which is limiting me. also it results in
pointless interview questions about sequence points.. :P

------
hardwaresofton
This slideset has shamed me. I definitely don't know enough about any of the
languages I use on a daily basis. I also thought I knew about C/C++.

------
dllthomas
Regarding padding, with GCC at least it's not (precisely) word size that it
optimizes for, but alignment constraints of the particular members. A short
will be bumped to a multiple of 2, an __int128 will be bumped to a multiple of
16. The alignment restriction of an entire struct is the largest alignment of
any member. This certainly has the intent and consequence of more aligned
loads.

------
enterx
Great story.

Deep understanding of the language used will make you do a better job.

This reminds me of the story that I've run into once. The junior developer
wanted to raise PHP's memory_limit parameter because his code crashed almost
every time while writing big file content to the output. He didn't know what
output buffering is and that he can turn it off and print the file directly to
the output. :D

------
shurcooL
Knowledge of the language is a big factor, but it's far from being the only
one. How fast one is able to create things is an example of another important
factor. There are many more.

------
skandl
Informative and thought-provoking presentation, but I think the mock interview
format is a disservice, as with it comes individual ideas of what a good or
useful interview is like.

------
talles
Despite all the discussion of the 'relevantness' of knowing a language in a so
deep level, I think this presentation is genius.

------
saejox
All of the quirks listed have good reasons to exist. Except size_t, that never
makes sense.

~~~
pcwalton
I don't agree. Just a few slides in, what good is "functions don't have to
return a value explicitly, even if declared as returning non-void" (a priori,
I mean—not counting backwards compatibility as a reason)?

------
bshanks
I think this presentation is interesting from a programming language design
point of view; if you were designing a new language, this presentation
highlights various 'gotchas' in C and C++ that might be the sort of thing you
would try to avoid creating in your new language.

Many of these fall under the heading of opportunities to apply the Pythonic
design criterion "refuse the temptation to guess":

1) in C, according to one of the comments, it was claimed (i didn't check)
that if you declare your own printf with the wrong signature, it will still be
linked to the printf in the std library, but will crash at runtime, e.g. "void
printf( int x, int y); main() {int a=42, b=99; printf( a, b);}" will
apparently crash.

\-- A new programming language might want to throw a compile-time error in
such a case (as C++ apparently does, according to the slides).

2) In C, depending on compiler options, you can read from an uninitialized
variable without a warning

\-- A new programming language might want to not auto-initialize any
variables, and to throw a compile-time error if they are used before
initialization.

3) In C, code like "int a = 41; a = a++" apparently compiles but leaves 'a' in
an undefined state because "you can only update a variable once between
sequence points" or it becomes undefined, but on many compilers works anyway.
A sequence point is "a point in the program's execution sequence where all
previous side effects SHALL have taken place and all subsequent side-effects
SHALL NOT have taken place".

\-- A new programming language might want to throw a compile-time error in
such a case

4) In C, the evaluation order of expressions is unspecified. so code like "a =
b() + c()" can call b() and c() in any order. If they have side effects then
this might matter, yet no compiler error is given. However, the evaluation
order of a() && b() IS specified.

\-- A new programming language might want to throw a compile-time error when
side-effectful code is called in context in which the order of evaluation is
unspecified.

Other miscellaneous gotchas:

5) In C, static vars (but not other vars) are initialized to 0 by default.

\-- A new programming language might want to either auto-initialize all
variables, or to not auto-initialize any variables,

6) The presentation says "C has very few sequence points. This helps to
maximize optimization opportunities for the compiler.". This is a tradeoff
between optimization vs. principal of least surprise.

\-- A new programming language which wanted to make things as simple as
possible would maximize 'sequence points', putting them in between practically
every computation step. But some new programming languages would choose to
minimize sequence points in order to allow the compiler to optimize as much as
possible.

7) The presentation says that the standard says that source code must end with
a newline.

\-- Imo that's a bit pedantic and the ideal programming language would not
care if code ended in a newline.

8) In one context (inside a function), the 'static' keyword is used to make a
variable persist across calls to that function. But in another context
(outside of any function), the same 'static' keyword is used as an access
modifier to define visibility to other compilation units!

\-- Using the same keyword for two different (albeit related) purposes is
confusing. A new programming language might either drop one of those features
entirely, or have a distinct keyword for it.

------
sanskritabelt
You know if someone's asking me these kinds of questions in an interview it's
the sign that something's deeply dysfunctional on the team and there's been
some kind of past trauma that makes them feel the need to ask.

That or they're assholes.

Either way, walk.

------
sanskritabelt
Got to slide 413. Get a freaking hobby or something. Maybe a dog. Go outside a
little bit.

