

Why I Chose to Learn C - dce
http://viget.com/extend/why-i-chose-to-learn-c

======
daenz
C really is fantastic language to learn. When I learned it, I also came from
the scripting language world (Python, PHP). Having that as a base, then
learning C, lead to revelations about how those scripting languages are
created, and how the data structures I took for granted in a scripting
language are actually implemented.

From what I understand in formal CS courses, you learn from the bottom up, but
learning from the top down was much more enlightening for me.

~~~
unlucky
I too started with scripting languages, and also learn in a similar way.
Hearing the value that learning C provided you makes the decision to learn it
myself a simple one.

To those versed in C, is the tutorial linked in the original article a
recommended one?

~~~
silentbicycle
I would enthusiastically recommend Learn C the Hard Way, even over K&R (which
hasn't aged well, for reasons LCtHW explains
(<http://c.learncodethehardway.org/book/krcritique.html)>).

------
dkhenry
C programming is still alive and well is many parts of our profession. The
biggest reason why is that even though c++ _can_ do memory management like C
most of the time programs implemented in it don't and you can really start to
loose a grasp as to what your asking the computer to do when you abstract away
where your putting all the stuff your unknowingly asking it to make.

~~~
mpyne
In the other hand, I find that C++'s ability to add semantics to memory
management is _extremely_ valuable in doing the right thing at all times.

unique_ptr<>, scoped_ptr<>, and shared_ptr<> all say different things about
heap memory lifetime, and those make it _easier_ to maintain your grasp on
what you're asking the computer to do.

Like many things in C++, you can do that in C too (e.g. by using a variant of
Hungarian notation). But the important thing is to do it.

~~~
drbawb
I've been playing w/ Rust this past week, and I've had something of an
enlightening experience related to the pointer semantics you describe.

Rust's memory management works similarly to what you describe in C++[0], but
things like unique_ptr, et al. are baked into the syntax and compiler. -- It's
basically syntactic sugar for memory semantics.

Coming from a background of GC'd languages (Java, Go, and Ruby) these
different allocation semantics were Very Hard(TM) for me to understand at
first. I kept battling w/ the type checker, throwing different pointer types
at it until the example compiled. (Rust's compiler is _very_ intelligent, w/o
using "unsafe" code, you basically cannot have a "use after free" condition in
Rust. -- It will not compile.)

As the parent points out: I've never really spent any length of time
_understanding_ the allocations I'm asking a computer to make. I just generate
things, they become garbage, and the runtime cleans it up eventually.

Once Rust "clicked" for me, I realized something: I know the lifetime of
_every single variable_ in this piece of code.

I know when it's allocated, where it's allocated, and when it gets freed.

The reason it was so hard for me to initially grok Rust was because I'm _not
used to reasoning_ about memory allocation.

Once I understood the semantics though, it was as though I had an _entirely
new_ level of abstraction at my fingertips.

These semantics are definitely some powerful stuff, and I'm very glad I'm
taking the time to try and understand them.

[0]: [http://pcwalton.github.com/blog/2013/03/18/an-overview-of-
me...](http://pcwalton.github.com/blog/2013/03/18/an-overview-of-memory-
management-in-rust/)

~~~
pjmlp
The biggest problem with manual memory management is when doing software in
large teams.

Suddenly you have distributed knowledge across team members with various skill
levels and producing memory leaks is very easy.

Nowadays automatic memory management in the form of GC or reference counting
is the way to go.

~~~
dkhenry
Or you can do what c++ and rust did which is neither reference counting or GC
( yes I know rust has a GC just stay with me for a little). Its a strong and
distinct message about what you plan on doing with the memory your getting.
When I run across a int* i don't know what your doing with it just by seeing
its type, but if I run across a shared_ptr<int> I know its reference counted
and will stick around until I am done with it and if I am the last one it will
be free'd. In the same manner If i see a unique_ptr<int> I know that if i need
it I must take it from someplace and the compiler will be kind enough to tell
me if I messed it up somehow.

~~~
pjmlp
I fail to see how that is not reference counting, even if implemented at
library level.

~~~
mpyne
shared_ptr probably does use reference counting, but unique_ptr doesn't.

There's literally only ever one "owner" of a unique_ptr, which is why the
parent comment talked about taking it from somewhere.

C++ exchanges ownership of unique_ptr's in the move constructor or assignment
operator (i.e. there's no "copy" operation available, unlike with
std::auto_ptr). If a unique_ptr still happens to own a pointer when the
unique_ptr is destructed, it knows to destroy the pointed-to object as well
and free the memory, but the object itself is not reference-counted per se,
there's only the Boolean sense "alive/dead".

~~~
pjmlp
That is still reference counting in any CS book about automatic memory
management algorithms.

~~~
mpyne
Only in the sense that

    
    
        MOV EAX, EBP
        XOR EBP, EBP
    

is "reference counting".

~~~
pjmlp
x86 implementation detail....

------
RegEx
For those who hit a wall with C when it came time to learn pointers, I'd like
to plug a YouTube video I made that people seem to really like.

<https://www.youtube.com/watch?v=IkyWCOUY8V4>

The terminology may not be completely accurate (although I did try very hard
to not say anything incorrect), but I honestly think it does a good job of
showing you how to actually use pointers. I know the resident C experts will
probably find something wrong, but I've received tons of comments and emails
from people saying they finally "get it". It's something I'm proud of.

~~~
mrweasel
I never really got why people found pointers to be complicated. I suck at
writing C code, but pointers are something I understood pretty easily. It in
the name really, it's something that points to (the location of) something
else.

I doubt that anyone struggles to understand pointers, they/we struggle to
understand the implementation of pointers in C, in some cases. If you want to
explain pointers, to people from a object oriented programming background, you
might start by comparing points to "by reference" and "by value".

My issue has always be why I would care about the memory address of a
variable, rather than getting the value as the default behavior, but that
might be why I suck a C.

~~~
RegEx
Just because you understood it great the first time doesn't mean everyone is
like you. I was turned off to C for a long time due to how awful my teachers
were at explaining the concept. My first time being exposed to pointers was in
a binary tree traversing algorithm handout given out by my teacher - it was
just way too much at once.

~~~
mrweasel
I just think it's weird that pointers are made to be so complicated, when the
part I don't get, which is header files, get no attention. Header files might
be the sole reason why I didn't care for C. I don't understand them and they
are never properly explained.

~~~
EliRivers
_I don't understand them and they are never properly explained._

There is nothing to get. They're just text, inserted wherever you told the
preprocessor to insert that text, exactly as if you had typed the whole lot in
yourself. What you choose to do with this ability is up to you. Many people
choose to use it to avoid having to copy the same text over and over again
into other files.

------
rayiner
Well now I feel old. When I was in high school, CS was a required course for
graduation and it was taught in C++ (that being the pedagogical language of
the APCS exam). It wasn't even that long ago (late 1990's).

~~~
mturmon
Here's another surprising (but fully understandable) perspective given in the
OP:

"Function pointers — It was interesting to me to see that such a low-level
language contained functional programming concepts."

If you started from assembly and worked up, this looks very different, because
at that very low level, functions and data look the same too. (Just like
Lisp).

~~~
alberich
How is that assembly has code as data just like Lisp? Is it possible to create
executable code during runtime, change the language's syntax, and stuff like
that, using assembly?

~~~
mturmon
Of course, I did not say assembly is just like Lisp in every respect.

But as long as we're picking nits --

It is of course completely possible to create executable code during runtime,
using assembler. Often not advisable. (Recall the punch line of:
<http://www.cs.utah.edu/~elb/folklore/mel.html>)

~~~
alberich
Reading the story on the link made me feel envy :)

I admire those who really understand how it all works under the hoods.

Although I tried to learn assembly on my own a long time ago, I never went
much further than reading some imput and printing it to the screen. It seems
it is a very specialized knowledge nowdays.

~~~
rayiner
The best way to learn assembler is by writing an assembler, which you can do
in pretty much any language you're comfortable with
(<https://github.com/rayiner/amd64-asm>) with just a manual
([http://support.amd.com/us/Processor_TechDocs/24594_APM_v3.pd...](http://support.amd.com/us/Processor_TechDocs/24594_APM_v3.pdf))
. I think x86 is really not a bad pedagogical tool. For all the crap it gets,
it's really a fairly clean architecture. And while we think of 32-bit and
64-bit extensions as having "piled on cruft" what's really happened is that
they have made the architecture conceptually cleaner and more orthogonal.

------
klrr
I learned C as first language. I haven't used it for any real-world work, but
it was fun way to get into programming. K&R told me not just C but how to
program, then I read TUPE which told me how to effectively use the best
development environment, Unix.

------
keithpeter
Quote below from _Learning C the Hard Way_

" _For Windows users I'll show you how to get a basic Ubuntu Linux system up
and running in a virtual machine so that you can still do all of my exercises,
but avoid all the painful Windows installation problems._ "

A bootable Ubuntu USB stick with persistent storage might be easier to get
started with? Can be created from a Live CD.

Interesting idea.

~~~
RegEx
I dual booted for about a year, and then I used virtual machines instead for
the last year. Using virtual machines has been a LOT easier. I use Lubuntu on
Virtualbox, and I don't plan on going back.

Things that annoy me about Ubuntu dual boot

* My Wacom tablet is terribly hard to configure on Ubuntu. * Flash support seems to be hit or miss in terms of out of the box functionality. Sometimes it works right when you install chromium, sometimes it doesn't * Windows weird partitioning. Windows will only let you have 1 or 2 of these special types of partitions on your HDD, and I somehow maxed out that partition count and couldn't fix it. It was very difficult to work with.

~~~
keithpeter
Whatever works with your hardware and use cases!

I was thinking more of a group of people meeting to work through the _Learn C
the hard way_ book, perhaps in a coffee bar or something, bringing their own
laptops. A bootable stick might make a C environment more accessible to them.

The puredyne project produced a bootable linux specifically to provide a
_common environment_ for training in audio production. Seemed to work for
them.

~~~
RegEx
If you bring a copy of the ISO you can have them all on starting from the same
Virtualbox install (takes 5 minutes to set up without knowing the software +
Ubuntu installation time).

But I've heard Vagrant is good for use cases like yours, though I haven't
personally used it.

That sounds like a fun activity by the way, have fun with that :)

------
sjtgraham
Re Valgrind: Last time I worked through CTHW, I couldn't use Valgrind because
of missing OS X 10.8 support and I felt like I was missing a lot by not using
it. I'm tempted to go back and work through it again, this time with a VM.

~~~
pekk
This is the kind of thing which makes OS X generally less productive for (non-
Apple) development than it could be.

------
zenbowman
Spending some time learning C, ML and Scheme is well worth it. Virtually all
modern languages derive from these three languages - and all 3 of them are
internally consistent enough to be beautiful.

------
nicholassmith
I know learning C might seem a bit of a waste of time, but given Obj-C, C++,
Python and Ruby can leverage it for performance it's not a bad thing to learn.

~~~
danieldk
Objective C and C++ can leverage it for performance? Objective-C is a strict
superset of C and C++ a near superset. If you learnt Objective C or C++
properly, you _already know_ C (!).

~~~
yk
While your statement is technically correct, in practice C is a very different
beast from C++/Obj-C. For example, in C dealing with global state is a
important problem, while one would just encapsulate the state in a object in
C++. So someone who learns just one of the supersets can easily miss all the
details which the additional features of C++/Obj-C hide.

