Solved What is a good free way to learn C?

It appears that to really be useful in the FreeBSD community, I will need to learn the C programming language. I am mainly learning C from http://c.learncodethehardway.org/book/. However, I would like to supplement that with some other sources when I am done to make sure I thoroughly understand C. Where are some other good places to learn C?

Also, any suggestions on how to build C programming skills after I learn it are welcomed as well.
 
LCTHW is certainly a great (work in progress) resource. Also consider Paul Gribble's "C Boot Camp" at http://gribblelab.org/CBootcamp/index.html

The best way to learn to code is to read and write code. Pick a project, look at the list of bugs, pick one and start working on it.

I also highly recommend "Expert C Programming" by Peter van der Linden. It is an outstanding book, well worth the time to read, and can usually be picked up cheaply second hand from that big Internet book store. Be sure to check the book's errata at http://www.afu.com/c/corrections.txt.
 
Thank you, the C boot camp has a large number of links and references, and I will strongly consider that book when I am done. I hope to soon be able to help improve FreeBSD, as it has served my so well in the short time I have used it.
 
A good way to learn C is to write programs in C. Of course you need to learn some few basics to start with, but then you should become productive. Write yourself small things and even bigger later. Are you able to program in other languages? Port your programs which you like very much to C.

To learn programming well you need two things which are probably the most important ones:
  • Time: a lot of time... it takes years of intensive work to learn the concepts of programming. C itself is not that time-consuming.
  • Motivation: you need to find problems that you can solve by programming or you will not get productive and, far more important, you will not feel any joy to have accomplished something.
  • Fill gaps by copying others: don't be afraid to look at code of other people. You can learn to understand many new things. If something is good, implement it yourself by looking at the code of someone else. This is only important while you are learning, later you will have a full repertoire of solutions for problems, because you have already had this or a similar problem before. This is only to keep your motivation up, because filling gaps sometimes completes your project and makes it useful.
I hope this helps.
 
Not that I am an expert but I learned C++ by writing a big program that did everything but in a practical way. The error reporting of clang(1) is great.
 
Good points by all. Especially about learning by writing the code for a project that interests you. I was an assembly language programmer who was begrudgingly forced to learn C from the "white book" years ago. Nowadays Google is your friend along with the man pages, StackOverflow.com, and a couple of sites that might explain things.

C is not a large, complicated language but you have to remember it won't do anything for you. You are in charge of it all so remember to keep track of all the pieces and clean up after you leave.
 
Thanks for the suggestions. I had done some work towards learning Python, but then I found that C made a lot more sense to me. If you count it, I know TI-BASIC, a scripting language for the TI-89 calculator (Texas Instruments). I eventually want to learn Python as well, but I have chosen to learn C first, since it is easier for me.

As for porting, the ports tree is quite extensive, and I am not sure what I would want to work on porting. Some things I would like to try working on in time though:
  • An OS level hibernate/sleep implementation (if that is not already in progress).
  • Bug fixes and improvements for the FreeBSD KDE port.
  • Clones of various Windows software, such as PC profiler (A Dungeons and Dragons tool).
 
Actually, after some thought, I realized FreeBSD lacks any PlayStation 1 emulators. I could work on porting one of those.

Edit: Darn it turns out you even have that. The FreeBSD community has done its job too well...
 
Not exactly free, but there are some books that you can buy, if you can find them.

  • The C Programming Language 2nd Edition, Brian W. Kernighan & Dennis M. Ritchie, ISBN 0-13-110362-8
  • C: How to Program, H. M. Deitel & P. J. Deitel, ISBN 0-13-118043-6
  • C by Discovery, L. S. Foster, ISBN ISBN 0-9624320-2-5
  • Practical C Programming, Steve Oualline, ISBN 1-56592-306-5

That last one is the book that I used to teach myself how to program in C. It's an O'Reilly publication. No matter what method you use, you have to read the material, write the sample programs, and do the exercises. That is the only way to learn it.
 
I like O'Reilly's books, I have one of theirs on Python which I haven't fully read because I decided to learn C first. Thanks for all of the suggestions.
 
Learning C and doing something useful in it would be two different things, often worlds apart. Learning a language doesn't automatically mean that you would do a Ph.D.

Here is the to do list to learn C, and a book for each step:
  1. Basic Language - C Primer Plus (6th Edition) by Stephen Prata.
  2. Datastructures and Algorithms - Mastering Algorithms with C by Kyle Loudon
  3. Advanced Programming in C - Object-Oriented Programming With ANSI-C (PDF) {Available free by author, google it}
Once you learn C, remember you still need to master the area of problem you need to solve. You can't expect yourself to be a FreeBSD kernel developer yet! Once you are done with C, the next step would be system programming:
  1. Basic Assembly and Computer organization- Art of Assembly Language, 2nd Edition by Randall Hyde
  2. NASM Assembly - Assembly Language Step-by-Step: Programming with Linux by Jeff Duntemann
  3. Operating System Development - Operating Systems: Principles and Practice by Thomas Anderson
  4. The Design and Implementation of the FreeBSD Operating System, 2nd Edition by Marshall Kirk McKusick
These steps aren't independent, they actually build upon each other. Where previous concludes the next improves from there and continue the journey. There is no magic way to do all this in less time, this might take at least two years even for a bright newbie.

But then, it is the fastest way to actually learn all this. The hit and trial method would take many years to learn the similar concepts.

I personally don't use C any more, I use a C subset of C++. Mainly because the libraries I need are mostly in C++ and porting the useful functions from it was a headache. And then std::string is simpler to maintain (compared to char*).
 
I will definitely keep all that in mind. It also sounds like I ultimately will need C++ and an interpreted language as well to really be effective.
 
I personally have done it the other way around and paid my price for it. So, here goes:

Learn at least two other languages first!

Strange as it may sound, there is good reason for that advice. Maybe most importantly because C is an "unfriendly hardcore" language, basically more a meta assembler than a high level language. That's why it's so powerful and that's why it's hardcore and almost inviting many errors. Finally that's why you should have quite some experience under your belt before you start with C.

Another reason is that C is immensely inefficient. That's by no means evil criticism! It's bound to be inefficient because that's where some of it power comes from.

Maybe it helps to see it from a certain perspective: there are extremely convenient languages like Python. They are really high level and quite typically untyped/typeless/dynamically typed. At the extreme other end there are assemblers. They are extremely inefficient (I'll come back to that in a second) and extremely powerful. And there is the middle ground with languages like Modula-2 or OCaml which offer a good (or even excellent) balance between raw power, efficiency, convenience, and security.

Ad "efficient/inefficient":

I use this simply as a term to describe the relation of time to develop vs features achieved. In a very high level language, for instance, I have hash maps available, I can simply write
Code:
todaysSoup = menu["monday"]
while in C I would need library calls and would spend way more time to achieve that functionality.

And there is of course what I call the "law of efficiency": It basically says that there is only a limited amount of efficiency available and one must chose how to balance it between rapid coding and rapid running.

That's where we are back at C. With C the answer is simple: The efficiency is at the rum time and all but absent at the development side.

So kernels are typically written in C while small userland utilities are typically written in scripting or shell languages.

Now, evidently no university would do operations on the heart of patients in a medical 101 course and no electronics apprentice would reasonably start with a FPGA design. Similarly, C or assembler should be approached only with lots of experience.

How to best learn it? You'll know yourself once you've walked the road of software development sufficiently long.

With which languages to start? With strongly typed and well equipped ones. Pascal comes to mind (it's probably not the finest language per se but there are excellent free tools available).

Finally a "golden rule" for guidance: when approaching a development task always use the language that offers just enough raw power but still the most convenience (and adequate safety!) possible.

And yes, there are quite few tasks (like kernels or drivers) that require C.
 
If I had the time (maybe I will take the time), I would know exactly what programming project I would do: I would try to port the following driver: http://www.broadcom.com/support/802.11/linux_sta.php. It is the Broadcom WiFi driver for my Macbook.

The beguiling thing of it is that you can download the code (it is in my home directory), it is there and I could, in principle, start. You can look at the source, and seemingly you are just some changes away from having WiFi on your Mac :) using FreeBSD. This would be a real motivation for doing real work.
 
Last edited by a moderator:
rmoe I have considered that statement a lot, and you are certainly not the first one to tell me to learn other languages first. I have looked at and spent a great amount of time on Python, and I have looked at a few others, however, I found that I strongly dislike higher level languages, especially Python. While I will agree C can be inefficient due to debug time and the possibility (or more accurately guarantee) of errors, however, I found that C has made a lot more sense to me and has proven far easier to learn than higher level languages. This is purely personal preference. I will agree, that ultimately I will need to have higher level languages as well.

One pseudo-analogy which might explain this (or might leave you permanently confused) is that I work better with more abstract and less symbolic representations of things. For example, I am the type of person who could easily find the roots of a polynomial equation, but I couldn't transform a shape to save my life. If this just confused you, I apologize.

On a side note, I did learn TI-BASIC, a BASIC-like language for Texas Instruments calculators, which gave me an initial understanding of programming (conditionals, variables, loops, etc.).
 
Well, go for it. I struggle with the higher level languages because I'm looking for control and don't feel I always have it unless I'm using C, or assembly.

Since electronic design is my background, I still follow the flow of the processor when I write code. I envision pointers as registers in the CPU pointing at exact memory locations. Even though I run a web development company, I still use C because, when I use other languages, I feel like it resembles C in parts but without the control and without knowing exactly what's going on. I didn't have to learn anything else to do what I wanted to do.

Sure, we have PHP and node.js and Python running for some of our things but that's because someone supplied an interface for those and we had to use it but give me C any day of the week, unless I can use assembly.

I miss those days. I had a boss who was an MIT graduate and he made us all buy the "white book" (but the first edition) and start coding in C instead of my beloved 68K assembly and I will never forgive him for that.

The only negative story I can tell about assembly is the time I spent three days debugging a program that insisted on lighting up one pixel on the screen. My eyesight was far better back then on those monochrome monitors but it took me three days to find that "MOV B" was not "MOV.B".

As far as this book goes:
Basic Assembly and Computer organization- Art of Assembly Language, 2nd Edition by Randall Hyde
Randy and I went round and round about High Level Assembly (HLA) years ago and I just don't see teaching one language to learn another. What he does is teach a between language that somewhat resembles C and somewhat resembles assembly to make assembly easier to learn. He used it in his college courses because he said he had students who couldn't grasp the concepts of assembly when they came from a high level language. However, once you learned HLA, you still had to learn the real ASM instructions.
 
One of the real advantages of open source is that you can choose the language to fit the problem domain. It does not have to be a one-size-fits-all solution, like it would if you had to buy compilers for each language.
 
wblock@ I agree with you on that bit, if I were using Windows, C wouldn't be a very viable option (mingw is limited, and I'd rather not get started on Microsoft's pre-made function collection).

drhowarddrfine I will eventually want to learn assembly as well, as I must agree one of my favorite aspects of C is the level of control. While I will look at the advice vyalmicro gave, I ultimately will start another thread when I am ready for assembly (which I estimate will be at least a year or two from now).
 
rmoe I have considered that statement a lot, and you are certainly not the first one to tell me to learn other languages first. I have looked at and spent a great amount of time on Python, and I have looked at a few others, however, I found that I strongly dislike higher level languages, especially python. While I will agree C can be inefficient due to debug time and the possibility (or more accurately guarantee) of errors, however, I found that C has made a lot more sense to me and has proven far easier to learn than higher level languages. This is purely personal preference. I will agree, that ultimately I will need to have higher level languages as well.

One pseudo-analogy which might explain this (or might leave you permanently confused) is that I work better with more abstract and less symbolic representations of things. For example, I am the type of person who could easily find the roots of a polynomial equation, but I couldn't transform a shape to save my life. If this just confused you, I apologize.

On a side note, I did learn TI-Basic, a basic-like language for Texas Instruments calculators, which gave me an initial understanding of programming (conditionals, variables, loops, etc).

I actually have taught C programming and I would think that I know a thing or two about the problem field at hand. But, no doubt, feel free to do whatever you please.

If you don't like Python, well, there are lots of other more or less high level languages out there.

What's the difference between C and other imperative typed languages anyway? Seen from a certain perspective it's more or less syntax and a couple of specifics. In the end it's always about implementing algorithms and data structures - et voilà, here you have your "more abstract representations of things"; even in Python (but maybe you meant "cryptic" or "cool"?).

So, evidently we have to look at more and other factors to find the right language for you or for a project.

Let me shine some light on C in some important regard. One point where lower level languages, in particular C, are strongly different from higher level languages is what many call "housekeeping" or, more abstract, the distance between an algorithm and it's implementation (in a low level language). In C, housekeeping cost is very high - and so is the power. Obviously the question is: "is the benefit/power (for a given project/situation) worth the cost/housekeeping?"

Generally, for any given problem there are many algorithms and approaches feasible. It's a mastery in itself to know sufficiently many of them, to decide which one is right for a given situation, to know the trade-offs, etc. And generally speaking every algorithm is implementable in every language.
Accordingly that mastery can be gained and trained in pretty much any language - and probably should be trained in two or three others less housekeeping and intense and error prone languages than C.

Keep in mind that the FreeBSD kernel developers aren't just (or even in the first place) glorious C programmers. First of all they are very experienced engineers. C is the tool they use because a kernel is one of the relatively few project types that actually are worth the cost of C (because the full power of C is needed).

That's my line. Pascal, to name one example, would be an excellent step towards your goal. Whatever language you chose, make sure there is a full set of good-quality tools available (like debuggers). Also, spend some time meeting and exercising completely different approaches like e.g. functional programming (you might actually like it). Once you have (maybe not a black but at least) a blue belt in algorithms, data structures, OS utilities, etc. you are ready for the final step toward C.

That's my opinion, based on quite some experience in both using and teaching C and having seen quite many people with quite diverse professional and experience backgrounds learning C.

If you feel like going right away toward C, there are plenty of books (pretending to) telling how to become a kernel hacker in two weeks and you have been given quite some suggestions here. I myself, however, can't do much more in that case than to wish you good luck (which I do).
 
rmoe I thank you for your considerable effort to provide advice. I don't believe I had explained myself properly, but I don't think I could either. For now I will likely continue learning C, although I will certainly take some time to try some other procedural imperative languages. Pascal itself seems useful since it is both compiled and interpreted with full support. I am picking C first due to preference (and the fact that I have invested a good bit of time into it already). However it is very clear I will need to learn an array of other languages to be effective. Pascal is definitely next in mind for me however.

I do understand the process of learning C will likely take me a couple of years, as while the "learn in two weeks" solutions may allow me to make a game, I wouldn't be able to do anything more. Part of the reason I made this thread rather than do an Internet search was to avoid bad resources, including those which claimed pipe dreams like that.
 
I think altogether, I would like to conclude this thread. I have learned quite a lot about C and I have built an extensive list of resources that I can use to learn it. I have also considered the implications of the ratio of my time to my computer's time, which is where higher level languages really start to shine, especially with programs that have light functions and wouldn't use a lot of resources no matter what language they are written in. No matter how I split it, to achieve a maximum level of productivity and effectiveness, I will want to learn five or six languages to build a toolkit, and use each one to its strengths (you can hammer a screw into the wall, but it's not as effective or pretty). Overall, I will admit, this thread has made me consider a much different approach to programming.

I have also learned that long term, being truly useful to the FreeBSD community has more far-reaching implications than simply programming. It is a complete life path that would require major decisions as well as significant effort, learning, and resolve.

I would like to thank everyone who gave resources and advice on this forum. I feel this will ultimately speed up my learning process for C and other languages. This has saved my a great deal of time and mistakes I otherwise would be destined to waste had I done just a simple Internet search.
 
Last edited by a moderator:
Just to avoid misunderstandings: I didn't mean to advise Pascal in particular as being superior in any way to similar languages. It just happens to fall in a similar league with C and it has very fine free tools as well as a not too small community. Obviously, Pascal will also show how to not implement some things (e.g. file handling).

I wish you success on your way!
 
Last edited by a moderator:
Just to avoid misunderstandings: I didn't mean to advise Pascal in particular as being superior in any way to similar languages. It just happens to fall in a similar league with C and it has very fine free tools as well as a not too small community. Obviously, Pascal will also show how to *not* implement some things ... (e.g. file handling).

I wish you success on your way!
Understood, older languages tend to have their limits, however, for me it seems like a nice language to try learning at some point as it falls closer towards elements I prefer in a language.
 
  • The C Programming Language
  • The Unix Programming Environment
  • The AWK Programming Language
If you cdr the above list you'll get the books that'll inspire you with the correct spirit that pervades the whole Unix/BSD world.
 
After learning C on a basic level, I will add now for those who may read this that source code is a resource I had greatly underestimated. Other nice resources are PDFs offered by MIT OpenCourseWare and library specific tutorials (e.g. An SDL tutorial).
I apologize if anyone is offended by potential thread necromancy.
 
Back
Top