

Essential C - krat0sprakhar
http://cslibrary.stanford.edu/101/

======
3amOpsGuy
C is an excellent first language when teaching in a CompSci type environment.

If the students are of a different discipline (not aiming to be CompSci grads)
or much younger then i think there are better choices e.g. Python.

In a CompSci academic setting i think learning assembly first (that is first
programming language but in parallel with the other classes such as computer
architecture etc.) is also a valid approach.

Programming from the Ground Up [1] is a very accessible introduction to x86
ASM and even supposing you don't go any further than the examples in this
book, you'll still feel the benefits.

[1]
[http://ftp.igh.cnrs.fr/pub/nongnu/pgubook/ProgrammingGroundU...](http://ftp.igh.cnrs.fr/pub/nongnu/pgubook/ProgrammingGroundUp-1-0-booksize.pdf)

~~~
jlgreco
I am split on if I think C/assembler is the best introduction material for
computer science, or if scheme is.

What I am rather certain of though is that just about everything in-between is
not. You don't really see the best of both worlds, but rather the worse.

(I should probably clarify that I think there is a large disconnect between
what makes a good language for teaching and what makes a good language for
software development in a corporate environment.)

~~~
_delirium
Those are two of the "pure" approaches, and recently there's a third one,
something in the ML/Haskell orbit. C for the low-level/machine-oriented
approach, Scheme for the lambda-calculus-esque approach, and ML/Haskell for
the type-theory-oriented approach.

Whether the Scheme approach is the best theoretical introduction depends on
part on how important you think type systems are to modern CS. Much of PLs
thinks the answer is "very important", since they view types as the basis of
rigorously specifying program behavior. Rob Harper has taken that view at CMU,
for example, using Standard ML in his revamped intro course. (I'm not strongly
opinionated on that subject myself.)

------
jorangreef
Trying to write JavaScript that takes advantage of a single engine such as V8,
hidden classes, type immutability, performance of 31 vs 32 bits, lack of 64
bit integer operations, cost of closures, etc. in the end, you spend so much
time trying to work within this indirection that C begins to look far less
wasteful and more direct, in terms of both human and machine time, especially
if you have the general design of what you're trying to do figured out.

~~~
derleth
This gets at one of the reasons I like Common Lisp: Common Lisp allows you to
program at a high level and then stepwise refine your program to make it more
efficient, such as by adding type declarations, adding other declarations,
changing your data types, and, at an extreme, changing your algorithms to run
without CONSing (that is, eliminating dynamic allocation and garbage
collection), not to mention whatever your specific implementation provides as
an extension to the standard.

Most code can stay fairly high-level, but the tools are there and a standard
part of the language if you need them.

~~~
agumonkey
I've seen some lispers going 'full stack' programming. Clojurians (like this
guy <http://www.learningclojure.com/2010/09/clojure-is-fast.html>) also aim to
cpu cycles when they program. It's an interesting workflow to prototype high
and fast and the project it down baremetal.

~~~
_delirium
The fact that Lisp systems have traditionally included an easy-to-use asm
inspector right in the environment is an interesting aspect imo. It's actually
_more_ common in my experience for Lispers to look at their generated asm than
it is for (non-embedded) C coders to do so, because it's so easy to just
(disassemble #'foo).

~~~
agumonkey
It's indeed nice to have direct connection between high and low. It's also in
lisp culture to unfold layers of code transformations rather than stay in your
own isolated layer and relying blindly on 'external tools' that will never be
as integrated syntactically and systemically as ... well lisp.

Lisp aside, having this point of view seems to be a good goal to reach.

ps: There's also one very important lower layer, the memory/cache subsystem.

------
etanol
The document talks about C89, even though the last Copyright year is 2003.
Isn't it about time that we start movin on? Where are the restricted pointers,
the flexible array member and so on?

And, by the way, I think the comment at the bottom of page 27 is not correct:

 _The qualifier const can be added to the left of a variable or parameter type
to declare that the code using the variable will not change the variable. As a
practical matter, use of const is very sporadic in the C programming
community. It does have one very handy use, which is to clarify the role of a
parameter in a function prototype..._

Actually, the use of _const_ is encouraged as it helps the compiler to catch
more errors as well as to enable some optimizations.

~~~
Danieru
I just spent the past 4 months programming a library in C89. I would have MUCH
preferred C99 if only for inline variable declaration.

The key issue for my project was being cross platform. Since Microsoft's
compiler does not implement C99 and never will, my hands were tied.

Now that's just my library. Other programers might be willing to decide case
by case which features of C99 to use. Still if the document dates back to 2003
then C99 support everywhere would have been even more primitive. C89 would
thus be the right decision for a introduction to C to avoid confusion.

~~~
nostrademons
I'm curious: could you write your program in the subset of C99 that'll compile
under C++, and then use C++ mode to compile it under Visual Studio?

~~~
Danieru
I suppose I could but that'd be too complicated for my taste. In fact I
wouldn't even need to go that far. Many of the most useful things are
implemented as extensions to C89 in the popular compilers. Instead I stuck to
pure C89 which I knew would be universally implemented. I like knowing that I
can set GCC to ansi + pedantic and have a reasonable expectation of no drastic
surprises.

C89 is primitive but charming in the simplicity. For instance while I disliked
being forced to declare a function's variables before any code I now see that
it encouraged me to keep functions very small. I would find ways to use fewer
variables. Instead of 'for(int i = 0; i < max; i++)' I would use 'while(--max
>= 0)', anything to avoid moving my cursor to the top of the function.

On the other hand I miss C++'s exceptions. Checking for errors all over the
place gets ugly and bloats the codebase. What would otherwise be a two line
copy operation between two objects gets two if blocks added which handle the
miniscule chance of memory allocation failure in some other deeper frame.

------
crag
I also thought C should be the first language anyone learns. Cause you learn
the most (about the machine) and other languages are easy peasy compared (well
except for assembler, of course).

~~~
derleth
> Cause you learn the most (about the machine)

Except when it comes to cache, pipelining, registers, non-uniform memory
access in general (not just cache), out-of-order execution and opcode pairing
rules, SIMD architectures, and the existence of the processor status word.
Other than that, yeah, C exposes you to a lot of worrying about memory
allocation when algorithm design would be a better use of your time.

> other languages are easy peasy compared

The only way you could possibly say this is if the only languages you know are
imperative Algol-derived ones with minimal type systems and no support for
logic or declarative programming. Learning C doesn't make Prolog meaningfully
easier. Learning C doesn't even make learning a mainstream language like SQL
easier.

~~~
dsirijus
This still doesn't successfully counter the statement that C is the best
language to start with.

I'm biased since C is my first language. Do you recommend another better
suited for the purpose?

~~~
Someone
I would recommend almost anything with an interactive shell over a traditional
C environment.

Python and irb are nice starting points because you can start out by claiming
they are just a calculator, where you have to press return instead of =.

From there, you can go to variables (prevent you from having to type, e.g. the
gravitational constant or a VAT percentage over and over), then to looping
(print multiplication tables), to arrays (store them for later use, or as
input for a loop to print year lengths for the planets, computed from their
distance to the sun), and then to functions.

And all of that without having to teach people the difference between source,
object code, and executable.

~~~
green7ea
I agree that this is the case for casual programming. If you are teaching
someone who has hardware experience (electrical engineer, etc), it is
sometimes easier to build from the bottom up and C is as low as it goes
without being assembly (a good and a bad thing).

~~~
jules
For the low level stuff an assembly language is way better than C. C is still
a LOT of magic that you won't be able to fully understand without
understanding how the machine and the compiler works. In assembly a line
corresponds to one instruction. What the assembler is doing is translating
each line to an instruction number that the machine can interpret. That is a
whole lot less magic than what happens in C. In addition, pointers are much
easier to understand from a machine perspective than from a C perspective:
they are just numbers indicating a location in memory. C makes that far too
complicated with different data types, pointers to local variables (and higher
up the call stack), confusing pointer declaration syntax, etc.

You can learn C syntax for assembly language idioms later. Starting out by
learning the concepts plus the syntax at the same time leads to inefficient
learning because when you're learning concepts like pointers it doesn't help
to have to learn confusing stuff and syntax at the same time.

This does not apply to languages that cleanly abstract the machine like
Scheme/Python/Haskell/what have you, but C lets the low level stuff shine
through so much that you end up having to learn that anyway; you can't really
learn it as an abstraction.

------
tiffani
I highly recommend this and a bunch of other C-related stuff in the Stanford
CS library. Their pointer explanations helped me many, many years ago.
<http://cslibrary.stanford.edu/>

~~~
manaskarekar
Along with Kernighan and Ritchie, I would also highly recommend getting a copy
of 'C: A reference manual' by Harbison and Steele. That book explains a lot of
stuff by topic and with descriptive examples. Especially beneficial for a
quick reference.

Highly recommended.

------
kawaguchi
I've been trying to get through K&R for the past week or so. I think this will
make things a lot easier. Thanks a lot!

~~~
e12e
Well, that kind of invalidates part of the comment I was going to write: "How
is this any better than K&R's 'the C programming language'?". I guess it all
depends on background and personal preference.

I've never become comfortable with C's pointer/reference/dereference syntax --
I much prefer Pascal in this sense. I recently had a look at Ada and was
pleasantly surprised -- it has a very straightforward syntax.

As other's mention here, I think C should be learnt with assembler (and
computer architecture - especially the bit about cache hits/misses). I find
that:

    
    
      http://www.drpaulcarter.com/pcasm/
    

is a great introduction to assembler and C -- and how the two (can) interact.

Another thing I find frustrating with C is that it's still a bit of a pain to
work with unicode/wide strings -- on my todo list is writing a short post on
"Hellø wørld (with unicode)" -- with some examples of wide strings in C,
(possibly Pascal) and ADA -- along with assembler output and a "pure"
assembler version.

There is surprisingly little good material on the web for this (that I managed
to find, anyway).

------
nuttendorfer
This looks like the perfect material to learn C if you already know how to
program (or at least in C-like languages like Java and C#).

------
jetsnoc
Nick Parlante is an exceptional instructor. I highly recommend Google's Python
Class he instructed.

------
sharms
I really enjoy the short / succinct format of this, does anyone have links to
similar documents for java / javascript / C++?

------
viraj_shah
Oh, this is fantastic. Thank you!

