
On becoming an expert C programmer - atdt
http://www.isthe.com/chongo/tech/comp/c/expert.html
======
kabdib
There's nothing magic about learning C versus any other language.

\- Read an authoritative source (K&R is good; there are better ones)

\- Read a bunch of good code (I mostly read tools and kernel sources)

\- Write crappy code and get better

Generally I want to write 10K lines of code in a new language before I
probably don't suck at it. Varies on the language and paradigm, going to C++
from C took like five years (figuring out OOP, and painful lessons on what to
avoid in C++), and apparently I'm never going to understand Haskell.

~~~
dpratt71
I'm a self-taught programmer. I started with Pascal (what seems like an age
ago), then C, then VB5/6, then C# and JS and a bunch of other programming
languages. At this point I felt like I could pick up about any mainstream
programming language very quickly.

And then I tried to tackle Haskell. That was about five years ago, and I think
I'm still at beginner/intermediate level with it. But I realized something.
These days I have a career and family. Back when I was learning Pascal, I had
a lot more time and mental focus on my hands. All the programming languages
I've learned since (besides Haskell) were not much different than Pascal, not
fundamentally so.

Haskell is fundamentally different. I definitely feel like my past programming
experience helped me learn Haskell faster than if I had no experience, but
that past experience was also a handicap. I had to discard a lot of
assumptions and get to a more basic mindset of what the art of programmming
entails. And like a lot of other folks, I found it to be a very rewarding (and
useful) experience.

~~~
V-2
Modern C# does provide some FP constructs (in the form of LINQ, lambdas etc.).
I know that having used them a lot made it easier for me to grasp Scala.

~~~
ultimape
I found the reverse to be true - Learning FP paradigm stuff in Scala helped me
pick up C#.

Finding out about Linq made me research functional-relational mapping for
Scala. FRM makes so much sense to me.

------
hackerboos
Whenever I've looked at an open source C programs, they go well beyond what
I've learned in K&R.

Learning C these days means mastering Make, autotools, macros, POSIX and Glib.

Knowing these is the difference between your contrived linked-list example and
creating software that can actually be deployed and is useful.

~~~
wlkr
You make an excellent point. Perhaps more so than with other languages,
getting to grips with making C actually useful relies a lot on quite extensive
knowledge of the build environment.

~~~
swartkrans
You also have to know about how computers work, how they represent numbers,
how and where they store memory, how computers process information, you have
to know about interrupts low level os stuff, networking protocols, physical
hardware limitations, debugging low level byzantine failures. You have to know
a lot more than just C syntax. I haven't even mentioned computer science, best
practices, working with others, architecture and UI topics.

------
informatimago
Not mentionned, about being an expert C programmer, is knowing the pitfalls of
C, (cf. undefined behaviors), and reading and knowing the ANSI C standard.

Of course, just knowing the language in and out is not enough, you also have
to be a good programmer in general (algorithms, "design patterns", software
architecture, software engineering, etc).

But writing C code without undefined behavior, and avoiding its numerous
pitfalls is absolutely necessary.

~~~
Htsthbjig
"Not mentionned, about being an expert C programmer, is knowing the pitfalls
of C, (cf. undefined behaviors)"

I am an expert in C, I had been decades writing on it and other languages, and
managing teams of coders. We created a company that used it a lot.

I can't understand what undefined behaviors C has, because it is the most
simple and defined language I do know of. I have lots of experience writing
assembler,fortran, Lisp, c++, python, objective C and also use C#, java,
javascript and other web languages and functional languages from time to time.

c++, java could be extremely undefined because the behavior depends on
conventions, committees and implementations. E.g we had to change some code
because of different compilers interpretation of the standars.

But c? c is basically portable assembler. If you understand how computers work
it is extremely reliable bar none. We have ported years of work of dozen
programmers in one day. With c++ and "write once, run everywhere marketing"
java we spent months.

It was also terribly frustrating for the team. Fontforge author had a similar
experience writing c++ compilers and that experience was so traumatic the
interface of Fontforge is so ugly as he does not want to use c++ with a ten
foot pole.

We try to avoid pitfalls more in high level languages because the programmer
has the ability to write code without understanding what is really happening
in the processor, or even in the program. Recipe programmers population is
growing a lot this days.

~~~
mahkoh
>If you understand how computers work it is extremely reliable bar none.

On my processor, INT64_MAX + 1 will be INT64_MIN, a negative value. But the
compiler is free to turn

    
    
      for (int64_t i = 1; i > 0; i++) {
      	f(i);
      }
    

into an infinite loop. Understanding how the computer works without reading
about undefined behavior will make you fall into these kinds of traps.

~~~
musername
missing overflow guards is just one of the big disappointments in c, if you
have experience with asm for any popular processor atm.

~~~
MrGando
Wasn't part of the scope of the language. It's a doble edged sword, but I
could see that being a good thing too. If you want raw speed, and know what
you're doing, it could be OK not to have overflow guards.

------
Animats
You're an expert C programmer when your C program has enough users that its
buffer overflows get CERT advisories from Homeland Security.

------
malkia
There is plenty of C code to look and learn: Linux, PostgreSQL, lua & luajit,
sqlite, redis, cairo, nanomsg, libuv, etc. etc

~~~
musername
Id's Quake and Doom sources are a classic in this matter. I looked a bit at
wsw, a fork of Quake 2. Now, my code is full of structs with function
pointers. It's like I just internalized the more elaborate syntax and now it's
all Hammers and Nails. I mean, function pointers to functions returning
function pointers, for example.

    
    
      typedef int (*foo) ();
      foo * bar ();
      foo * p = bar;
    

not rocket science, but ambiguous at first sight when compressed to one line.
I hope that kind of syntax is as complicated as it get's, because I'd like to
think C semantics aren't really difficult. That is until implementing
customized data types on top.

As mentioned in another comment, learning the toolchain is just as important
and it's not without reason, that Don Knut takes forever writing about
compiler design. Never mind the ventures into the algorithmic side of things.

~~~
readerrrr
[http://ideone.com/ZOvq0n](http://ideone.com/ZOvq0n)

You probably meant this:

[http://ideone.com/wuZI2o](http://ideone.com/wuZI2o)

~~~
musername
thanks. welp, I'm still learning

~~~
readerrrr
Consider using ( void ) instead of () when declaring anything with zero
parameters.

------
dkarapetyan
This answer
([http://programmers.stackexchange.com/a/229245/7146](http://programmers.stackexchange.com/a/229245/7146))
is about managing code complexity but the lesson applies equally as well to
becoming a better programmer with any language.

------
jfaucett
For me c is kind of a wierd language. Wierd in that the language itself is
incredibly simple, I think anyone could learn c syntax and usage in about 2
days max. But I think where most people get hung up with on c are the
concepts, you do need to know about compiling and linking, static vs dynamic
libs, lots of details about how computer architecture / memory works, and to
get anything done you need know POSIX and the concepts behind any libraries
you use. Its not like ruby or other dynamic languages where you could
basically have no idea how HTTP works and still write a webapp.

~~~
claren
The development of a (good) web-server in pure python likely still requires
knowledge of language internals. If depending on libraries, it just depends on
the libraries. Web frameworks with "Batteries included" seem rather rare on
the C shore, though, maybe because statically compiled languages are in
general not used as frequently in web-development. Therefor it's an unfair
comparison.

To leverage C's power, libraries should also tend to stay general enough, too,
no?

Most compilers or interpreters are complicated under the hood. Fixing a bug in
the compiler to get your code working (and submitting a patch), that's
mastery.

------
vezzy-fnord
Freecode is now frozen, but you may want to check out its informal successor
Freshcode: [http://freshcode.club/](http://freshcode.club/)

------
bithush
C is still my favourite language. Sure it has issues but it works how my brain
works or is it my brain works how C works? Either way it just makes sense to
me.

------
greyman
In my experience, one of the easiest ways is to just get employed by a
company, where coding is done in C. You will have to code in that language a
lot and the colleagues can help you. I also learned a few languages myself in
my spare time (PHP, Python), but that is not nearly as effective.

If you want to really be an expert on C (or in anything imho), you just have
to do it fulltime.

------
neduma
> Always, always, always write code as if it will last 30 years.

Well said. But if i do 'git blame' and see a code is like 30 years old. First
thing to come to my mind is it must me some kind crappy old legacy code

I know it is wrong. It is substance that matters. But lately somehow i
programmed to myself to like newer code then older code. I need to step out
that misconception.

------
goldenkey
C is a cakewalk compared to C++ but a lot harder to do right, even when
experienced, because of its more low level constructs

~~~
general_failure
Sure. Climbing a mountain is a cakewalk compared to descending an erupting
volcano as well.

The analogy being that C++ appears to make things simpler (descending) but the
destination is filled with peril.

------
101914
"DBell is one of the best programmers on the planet."

How would one verify this?

I tried a couple of his sample C programs.

One of them was one source and one header file and compiled easily and
quickly. A+. But then I looked at what the program did and realized I had
written several iterations of the same utility myself years ago, using only
the shell, sed, tr and ed or vi. I guess maybe his point of writing this in C
is that he envisions a system that lacks those programs?

Then I tried another sample, which was a little more complex.

It failed to compile. Looks like he assumed Linux but failed to state the
program is not portable. F.

I am always on the lookout for truly great C programmers.

Is DBell really as good as Noll says?

~~~
ciupicri
It would be good if you could mention precisely what programs have you tested
and perhaps provide some links.

~~~
V-2
I agree with 101914. See my comment:
[https://news.ycombinator.com/item?id=8511826](https://news.ycombinator.com/item?id=8511826)

------
eplanit
"It is somewhat easy to write a program that works. It requires practice and
effort to write code that you can maintain and support."

Truer words were never spoken.

------
V-2

       Look at some of DBell's code:
    
       http://www.tip.net.au/~dbell/
       http://www.isthe.com/chongo/tech/comp/calc/index.html
    
       Learn from it. DBell is one of the best programmers on the planet.
    

I have nothing against Mr DBell, whom I don't know, but... don't learn from
it, please.

    
    
       Weather 1.9 - Java application to plot weather observations from the Australian Government's Bureau of Meteorology (BOM) web site.
    

I did look at it.

Controller.java is over 1200 lines long. Don't learn from people who create
classes that big (aka God objects).

SunriseSunset.java contains nearly 100 lines of commented out code. That's
another bad practice.

What's more, it consists mostly of a main method commented as "Simple main to
test the class". This is a so-called poor man's unit test, it doesn't use
assertions, it just prints some results out to be verified by the programmer
manually. Which is another antipattern.

His FileInfo.java (part of his FileSelection 2.0) contains tautological
comments like:

    
    
        //
        // Get the suffix path.
        //
        String suffixPath = fullPath.substring(prefixPath.length());
    

Gee, you don't say. Redundant comments, another antipattern.

isDirectoryEmpty (in the same file) happily ignores an exception:

    
    
        boolean isEmpty = true;
    
        try
        {
            stream = Files.newDirectoryStream(directoryPath);
    
            for (Path path : stream)
            {
                String name = path.getFileName().toString();
    
                if (!name.equals(".") && !name.equals(".."))
                {
                    isEmpty = false;
                    break;
                }
            }
    
    	stream.close();
    	stream = null;
        }
        catch (IOException e)
        {
        }
        finally
        {
            Utils.safeClose(stream);
        }
    
        return isEmpty;
    

Meaning that if an IOException occurs (for whatever reason), the method will
tell you that the directory is empty, even if that's not true.

Setting stream to null after closing it makes no sense whatsoever (it's a
local variable, it's not going to survive exiting the method).

Closing it in the try block makes no sense to me either, because
Utils.safeClose is going to execute either way; that's how the finally clause
works. It looks like the author assumed that finally only executes if an
exception happens. No, it is run in either case.

So, what's the point of closing the stream twice? And if it does serve some
purpose, now that would require leaving a comment, because it's totally
unobvious. Not "getting the suffix path", which is blatantly obvious.

I could go on. This is poor quality code, I'm hardly a great programmer
(working on it!), but it's not up to my production standards.

If the man is "one of the best programmers on the planet", the planet can't be
Earth.

~~~
desdiv
>So, what's the point of closing the stream twice?

The first stream.close() does not get executed if an IOException occurs.

~~~
jacquesm
The whole point of a finally block is to have the cleanup code in it that
should be called regardless of whether or not an exception occurred in the
first place.

So the first stream.close should not be there if the 'finally' block already
contains one, and it _will_ be executed twice if an exception does _not_
occur.

------
xxcode
The article advises learning to play music because a lot of good programmers
play music. A lot of programmers are also white. Please become white if you
can.

~~~
vezzy-fnord
Not a valid comparison at all. One is a learned skill, the other is an innate
phenotype.

~~~
V-2
That's true, but the point is that this correlation could be pure coincidence,
or at least not causative. (If it actually occurs to start with - it would be
interesting to create a poll and verify whether most reputed programmers are
indeed more musical than general population.)

Many programmers have stereotypical geek interests like RPG, Star Wars etc.
but it doesn't mean that these contribute to their programming skills in any
way. Being socially awkward doesn't make you Sheldon Cooper :)

~~~
rdc12
Except there is a large body of research which shows the effect of music on
cognitive ability to support the assertion

