As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am new to C programming and I am having problems understanding common pitfalls and common usages of different library functions in C programming. Can some one point me to a good resource where I can learn subtleties in C programming. Also can some one point me to a good resource learn debugging tools like gdb.
Also I want to know what is the difference between char *c="hello"; and char c[10]="hello" . Can some one tell me which one is recommended over the other in different situations.
Thanks & Regards,
Mousey.
char *c = "hello";
That makes c a pointer and is pointing to memory that should not be modified (so you cannot modify the data). But since c is a pointer, you can change where it points to.
char c[10] = "hello";
That makes c an array and arranges to have the array initialized with the specified string. Since it's an array, you can modify the data (although make sure you don't overflow the buffer) but you cannot change where in memory c references.
Just read The C Programming Language and write code. If you're new to it then you need first-hand experience so you can learn what the subtleties are. Just reading a list won't help a huge amount.
For the language itself, the book by the language designers is a good read. Be sure to do the exercises.
Another useful resource is the comp.lang.c FAQ. You've asked question 6.2 (be sure to read 6.1 and 6.3 as well).
It's explained in the links above, but just to insist: pointers and arrays are not the same thing in C. Rather, there are circumstances where the language requires a pointer, but you can use an array instead and it'll be converted automatically.
The difference is as follows:
char *c = "hello";
Created several things:
a char* called c
a static string in memory filled with "hello\0"
and it sets c to the address of that static memory
Whereas:
char c[10] = "hello";
Creates:
a char* called c (See note below)
10 slots in memory someplace
sets c to the address of the first location in the above
and it treats "hello" like {'h','e','l','l','o','\0'}, thus copying those values into c[0] through c[5]
depending on the compiler, "hello" may or may not get allocated someplace in memory in addition
Note:
In the second case, there technically isn't both an array and a variable that exists just to contain the address of the array, it just seems that way. So c is really just an alias for the address of the first location in the array. Updated with info from Tim below in the comments.
For gdb, the docs are online http://sourceware.org/gdb/current/onlinedocs/gdb/
And a cheat sheet which I find much more useful: http://users.ece.utexas.edu/~adnan/gdb-refcard.pdf
My first recommendation would be that unless you have a really good reason to learn C specifically, learn C++ instead. I realise that is probably going to be contentious amongst some; just something to consider if you have not already done so.
For resources, in the first instance a good book is always best, but if you are looking for on-line resources then you will find that many are C++ related, some deal with C and C++; different styles of writing and presentation suit different users; try some of these:
http://www.cprogramming.com/
http://www.howstuffworks.com/c.htm
http://www2.its.strath.ac.uk/courses/c/
The C Book (online)
The C Book (HTML download)
The C Book (PDF)
The following C++ related sites include excellent coverage of the C standard library:
http://www.cplusplus.com/
http://www.cppreference.com/wiki/
With respect to GDB, I applaud the appreciation of the benefits of using a symbolic debugger, it is remarkable how many developers avoid this essential tool, but suggest that using raw GDB may put you off such tools for life. If you are able to use VC++ on Windows its debugger is second to none, and VC++ Express is free. If you must use GDB (because you are using Linux for example) I suggest that you use GDB integrated into an IDE such as Eclipse, or KDevelop, or use the stand-alone Insight debugger. If you do choose to be hardcore and use GDB directly, there seems to be few resources on how to use it effectively beyond the GDB manual itself. There is also Debugging with GDB: The GNU Source-Level Debugger at $30.
If you're mathematically inclined, Project Euler can probably give you some good practice in certain areas, especially in array manipulation and stuff.
But keep in mind, there's more to programming than math -- despite what your prof might tell you.
The "C Traps and Pitfalls" by Andrew Koenig is an excellent book precisely for learning about C pitfalls. It is a pretty thin book, though. The comp.lang.c FAQ someone else pointed to is also an excellent resource.
Try doing a search for "c programming puzzles" and you'll find lots of resources on the tricky subtleties of the language itself (and there are many). Eg. here
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Member functions can be emulated in C by passing the this pointer explicitly. Virtual functions can be emulated by explicitly storing in every object a pointer to a global array of function pointers. Fine.
Now my question is, do people actually do this? I am wondering if it's worth teaching this technique, because I do not want to teach something to C freshmen that is practically never used in the real world.
(I need to fill the last day of a two-week introductory C course for people already familiar with OOP.)
Are there any relevant projects, libraries or frameworks that emulate OO in C in the manner described?
I've about twenty years experience in C. It was the first compiled language I learned and I've never needed to move on, so it's been C and only C, all the way. I write code constantly at work and at home. I have published a library of lock-free data structures. I think I'm a competent C programmer.
With regard to your question, OO consists of a number of concepts. One, for example, is instantiation, e.g a library with a new() and delete() and instances of a given entity (stack, list, etc). C supports this and it is, of course, a very functional and useful approach. I've used this approach for about fifteen years.
Many years ago I began experimenting with another OO concept, well supported in C++, inheritance. I wanted an entity which contained other entities. The problem then is exposing the API of the contained entites. You can do it, but the fact is, the C language does not naturally express such an concept and approach. It is not something I now use.
My advice is; a knife is a knife, a fork is a fork. You can use either as the other, but it doesn't work well. C does not naturally support some (important) OO concepts, such as inheritance. Don't try to make C do these things. If you want to do this, use C++.
Yes, they do.
Are there any relevant projects, libraries or frameworks that emulate OO in C in the manner described?
I wouldn't call it "emulating" just because there's no first-class language support. See GObject.
A lot of project uses the Object oriented paradigms in C codebase. For various reasons they don't use CPP directly. For system level or performance intensive projects, Other languages don't cut the deal. So its a battle between cpp and c.
Why people emulate OO in C instead of full blown CPP is topic of heated arguments. Linus torvalds once famously stated, CPP compilers are not trustworthy. He has little faith on CPP generated code.
Linux kernel is a good example of implementing OO design patterns in C. You can read about how Linux kernel did it in this lwn.net article series :
part1
part2
There is a extensive free document lying around in internet which covers a full range implementation OO design patterns in C.
ooc.pdf
You can find many other projects along the same road.
Examples:
pjsip
sofia
It may not be used in practice, but it is incredibly valuable to learn the concept of the equivalence between member functions and functions that take the object as the first parameter. Having this concept in the back of their head will help them in many problems they will encounter down the road.
Day in and day out I see people asking questions on Stack Overflow about why it doesn't work to point to pass a member function to something requiring function pointer, and things like that. They think that member functions are just some magical functions that are part of an object, and over-complicate the whole situation. If they had realized that member functions were equivalent to functions that took the object as the first parameter, then the problem they're having (that to call the method they would somehow need both the member function pointer as well as the object), as well as possible solutions (somehow pass the object in separately, or make some kind of closure that captures the object) becomes apparent. Apparently, too many people just pretend that OO is "magic" and don't understand this.
In functional programming, we often teach people how data structures and local variables and all that stuff could be written purely in terms of manipulation of functions. Not that this is practical -- it would probably be inefficient -- but this impresses upon them something about the power of functions. And it helps them to understand things in a different way. And maybe down the road if they write a compiler or something, these equivalences will come in handy.
Computer science is all about equivalences and reductions, and how to think about one problem in terms of another. We reduce SAT-3 to subset sum, not because that's actually how we would actually solve the SAT-3 problem, but because this teaches us that subset sum is NP-complete.
Every once in a while, I come across a piece of code written by someone else, where non-instance methods take a pointer to a structure as an argument, and I see a pattern and a light bulb goes off in my head, and I say, ah-ha, this can be re-factored into an instance method, because I know about this equivalence. So you see, knowing these equivalences also helps us to write better, simpler code.
Check out TI's "DSP Algorithm Standard" / xDAIS framework.
There's a generic C API that every conforming DSP algorithm implementation implements (sorry for the tautology). The need for all this "art" stems from several issues common in the DSP world:
relatively small RAMs
multiple data channels (often parallel/concurrent)
complex algorithm usage patterns
something else I forget
The standard and framework aim at making it easier for DSP engineers to use 3rd party DSP algorithms.
There's an interface to configure an algorithm instance and query its memory requirements (based on the configuration) and there are support functions that actually manage the memory.
Some memory areas, scratchpads, can be allocated temporarily and given to an algorithm instance when it's active and taken away from it when it's inactive and given to another instance, effectively shared.
There's also functionality (and APIs) to move instance memory buffers to defragment memory.
There's more, but I'd need to reread the docs to recall the details.
See IALG_*() and ALG_*() interface methods for example.
Also, there are tools to validate implementations of the generic APIs. 3rd parties can request official validation of them from TI.
Some relevant links: spru352g.pdf, spru360e.pdf.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
My current experience with programming is limited to hacking together some shell scripts and some assembly in the past. However, I learned the basic syntax of C code in college.
I want to learn how to write efficient C code, I an confused whether to start with K&R or C Programming: A Modern Approach. Also should I study some algorithm books alongside so that I don't end up writing inefficient code right from the beginning?
Don't worry too much about efficient code at this stage. Concern yourself more with clear and readable code.
As a rule, keep functions small, performing one task. If it takes too many sentences to describe what one function does, it probably needs breaking down into smaller functions.
Use descriptive variable names, rather than just x and n etc.
Start by writing programs you will enjoy developing, rather than "boring exercises that the book tells you to do." However, do follow the book's advice and guidelines.
Everybody has their own style, don't worry if your style doesn't quite match the next person's.
Above all, enjoy it! If you find learning one thing a bit boring, move on to something else, there's always loads to learn.
EDIT: Additionally, don't try to run before you can walk - I'm specifically thinking a) pointers and b) dynamic memory allocation. There's no need to use either of them at this early stage until you're comfortable.
First get wet with the basics. Learn the gotchas, learn a good C style. You can't learn how to write efficient C code in one run, so it's okay to make mistakes in the beginning.
I found the best way to learn how to write efficient code is to learn how to avoid memory leaks.
Maintainable C code requires good documentation and comments in the source. Also, it requires writing code that resists change.
Examples:
bad example:
int* ptr = malloc(5 * 4); //4 here being size of int.
... do something with ptr here... //<-- this is wrong!
Why bad? int may not always be 4. Also, in the second line you're doing something with ptr (probably assignment) without checking if it was NULL.
better example:
int* ptr = malloc(5*sizeof(int)); // better, always allocate with respect to int size
if (ptr) ..do something..
Why better? First you allocated with respect to the size of int, so even if in another architecture int's size differed, you are good.
You also check if ptr is NULL before using
Best example:
int* ptr = malloc(5* sizeof(*ptr));
if (ptr) .. do something.
free(ptr); // done with ptr
Why is this the best way? First you linked the size of allocation not with int's size, but directly with ptr's type. Now if someone for any reason changed int to long in ptr's declaration (especially if it was declared somewhere else) without changing to long inside malloc's argument; your allocation will still be correct because it directly allocates according to whatever type ptr is of.
We also free'd ptr after being done with it, to prevent a memory leak.
You should try reading "Writing solid code" from Steve Maguire, it's an old book, but it can teach you what you need.
First and foremost, care for portable programming. There is a C Standard (ISO 9899:1999 aka C99 and :2011 aka C11--you need to invest ~20 bucks) and a "Unix" Standard, called POSIX (freely accessible). Read them, live them. Stay away from any and all Windows and graphics programming until you're no longer a grasshopper.
As the wise man says: The novice programs his machine. The expert programs a set of machines. The guru programs for no particular machine.
That's the essence of portability and it will save you from a lot of questions of the form It compiled/ran under FOO-OS with the Frobozz magic compiler, but doesn't under BAR-OS, WTF?
To add on to what others have said, I would recommend just writing a lot of code. Often I find that people in this field wait too long to actually code, and spend too much time reading.
You can emulate object oriented programming.
Define entities by defining files containing structures, and functions operating on these structures. Mark functions that do not need to be seen outside as static. This will keep them hidden, so you pollute less the namespace. Create a new structure with a new function that returns a pointer to the newly malloc()ated structure, and a delete that performs the free(). Define simple members that operate on the structure data, accepting a pointer to the structure always as a first argument.
I suggest you to learn some OOP with python, and apply the same concepts.
To be honest in my opinion you start learning c++ which is an advance version of c language having better and efficient code here is a link that would given you a start..
Link http://internetseekho.com/learn-the-write-way-to-code-in-c-part-4-getting-data-from-user-and-displaying-it-on-screen/
I'm a web coder: I currently enjoy AS3 and deal with PHP. I own a Nintendo DS and want to give C a go.
From a higher level, what basic things/creature comforts are going to go missing?
I can't find [for... in] loops, so I assume they aren't there. It looks like I'm going to have to declare things religiously, and I assume I have no objects (which I dealt with in PHP a while ago).
Hash tables? Funny data types?
To sum it up, you'll basically get:
Typed variables
Functions
Pointers
Standard libraries
Then, you make the rest -- that may be a little too simplified, but that's a rough idea of what to face.
It can be daunting to begin with and there may be a learning curve to overcome. Here's a few speed bumps you may encounter:
String? What string?
One big thing to get used to would be strings. There is no such thing as a string in C. A string is a "null-terminated character array" (sometimes called C strings), which basically means an array of type char with the final element being a \0 (char value 0).
In memory, a char array of length 4 containing Hi! would appear as:
char[0] == 'H'
char[1] == 'i'
char[2] == '!'
char[3] == '\0'
Also, strings don't know their own length (no such things as "objects" that come for free in C), so the use of standard library call strlen would be required, which more or less is a for loop that goes through the string until it hits a \0 character. (This means it's an O(N) operation -- longer the string, longer it takes to find the length, unlike O(1) operation of most string implementation in modern languages.)
Garbage collection?
No such thing is as a garbage collector in C. In fact, you need to allocate and deallocate memory yourself:
/* Allocate enough memory for array of 10 int values. */
int* array_of_ints = malloc(sizeof(int) * 10);
/* Done with the array? Don't forget to free the memory! */
free(array_of_ints);
Failing to clean up after allocation of memory can lead to things called memory leaks which I'm sure you've heard of before.
Pointers!
And as always, when we talk about C, we can't forget about pointers. The whole concept of references to variables and dereferencing pointers can be a serious headache-inducing concept, but once you get a hang of it, it's actually not too bad.
Except for the times when you expect it to work one way, but you find out that you didn't quite understand pointers well enough and it actually does something else -- as they say, been there, done that.
Oh, and pointers are probably going to be one of the first times you'll actually see a program crash bad enough that the operating system will yell at you. A segmentation fault is not something the computer likes a lot.
Types
All variables in C will have types. C is a statically-typed language, meaning that variable types will be checked at compile time. This might take some getting used to at the beginning, but can also be seen as a good thing, as it can reduce runtime errors such as type errors where you try to assign a number to a string.
However, it is possible to perform typecasts, so it is possible to cast a int type (which are integer values) to a double type (a floating type value). However, it is not possible to try to cast an int directly to a string like char*.
So, for example, in some languages the following is allowed:
// Example of a very weakly-typed pseudolanguage with implicit typecasts:
number n = 42
string s = "answer: "
string result = s + n // Result: "answer: 42"
In C, one would have to call an itoa function to get a char* representation of an int, then use strcat to concatenate two strings.
Conclusion
Those things said, learning C coming from a higher language can be very eye-opening and probably challenging to begin with, but once you get a hang of it, it can be pretty fun to work with.
I'd recommend starting to experiment with a C compiler, and have a good book or reference.
I think many people will recommend the K&R book, which is indeed an excellent book.
At first, I didn't think recommending K&R as the first C book would be a good idea because it may be a little bit on the difficult side, but on second thought, I think it is a very comprehensive and well-written book that can be good for getting into C if you already have some programming experience.
Good luck!
Well ... You might be in for something of a culture shock. These are the 32 standard keywords in C, and that includes the basic types.
C's standard library is pretty functional (more so than people perhaps expect), but very very thin when compared to what higher-level languages give you. There is no hash table in sight, and you are correct to assume that C does not have syntactic or semantic support for objects.
It is possible to write pretty object-oriented code anyway, but you will have to jump through a few hoops, and do much more manually since the language won't help you. See for instance the GTK+ UI toolkit for an example of a well-designed object-oriented C library/API.
I'm a web coder: I currently enjoy AS3 and deal with PHP. I own a Nintendo DS and want to give C a go.
Why do you want to do C programming?
What are your reasons, what do you hope to achieve?
Is it in order to write software for the Nintendo DS?
From a higher level, what basic things/creature comforts are going to go missing?
Given your background, I think you'll personally miss the lack of dynamic typing support, in other words you will have to be very explicit in your C programs, your data must be specified with proper types, so that the compiler knows what type of data you are working with. This also applies to any sort of memory management, i.e. basically anything once you start working with data structures that are non PODs.
For example, where you would do something like this in php:
function multiply(x) {
return (x*x);
}
You would have to do something like this in C:
int multiply(int x) {
return (x*x);
}
While these may seem fairly similar, there are big differences, namely typing restrictions: the php version will also work with floating point values, while in C you would have to explicitly provide versions for different types and ranges of values (C types are constrained to certain ranges).
I can't find [for... in] loops, so assume they aren't there
in C, it looks more like the following:
int c;
for (c=0;c<=10;c++) {
// loop body
}
it looks like I'm going to have to declare things religiously
Yes, very much so - much more so, than you'll appreciate
and I assume I have no objects (which I dealt with in PHP a while ago).
correct, no objects - but OOP can still be emulated using other ways, such as function(struct obj)
Depending on your goals and motivation, I think you may find C a pretty frustrating language to start serious programming with, you may want to look into some of the related alternatives like for example Java instead.
Dynamic arrays and garbage collection. It's not built in to C so you'll need to roll your own or use a pre-existing solution.
The standard procedure is that you manage the memory yourself which might sound like something horrible but it really isn't. For example in AS3 and PHP you can create an array and forget it when you're done with it. In C you'll have to make sure to deallocate it yourself or memory will leak and bad stuff can/will happen.
You'll particularly miss automatic memory management, and semantically meaningful datatypes such as strings, tables &c. However, learning C well is quite instructive, even though you probably don't want to use it for application-level programming, so I suggest you grab a "K&R" (Kernighan and Ritchie's seminal book) and give it a go -- you'll find plenty of free libraries on the web to use and study as you proceed beyond that, though you'll have to discipline yourself to use proper memory management heuristics... happy learning!
I was just doing some research online, and it seems there's a viable possibility to use lua for developing on the "nintendo DS", this may in fact be the easiest way for someone familiar with high level languages to get started doing embedded development, without sacrificing too much HLL power and without experiencing the inevitable culture shock when migrating from a HLL to C: microlua, here are the API docs.
So you might want to give it a go, possibly using an emulator for starters.
Keep us posted!
I'm pretty sure you want to be looking at C++, not C. C++ is basically object oriented C.
What you'll REALLY miss is the ability to rapidly prototype and test changes. You can't just change a line of code and run. Even using build tools like "make" a recompile can often take several minutes. This is even worse when you consider that it's really easy to make mistakes in C/C++. On large projects I reckon I spend more time compiling than actually coding. As a long-term user of script languages this is my biggest issue with using C.
Moving directly from a higher-level language running on a machine with effectively infinite resources to a DS is going to be a challenge, and not just because of the language.
The Nintendo DS has only 4MB of RAM, a 66MHz ARM-7, no operating system, and the development libraries available (such as libnds) provide only a thin abstraction over the hardware itself.
So, in addition to having to deal with manual memory management, a simpler language with fewer creature comforts, static typing, lack of objects, and the need to run a compile step before you can see any changes, you also have to deal with memory fragmentation, a very slow CPU by modern standards, and needing to interact with the hardware directly in order to do anything useful.
Writing code for the DS, the only other option is C++. You can't use a lot of the advanced features that make C++ worthwhile on such a limited system. You'd be writing C code using a C++ compiler.
That said, it's a lot of fun. You can screw around with the hardware all you like, and there's no need to interface with the operating system, because there isn't one.
C is the next level above straight assembler and allows you to operate close to the metal. This gives power to do amazing stuff but also to easily shoot yourself in the foot!
One such example is direct memory access and the perils and wonder of pointer arithmetic. Pointers are very powerful, fast, and handy however require careful management. See this SO question for an example.
Also as mentioned by the other answerers you will have to do your own memory management. Again powerful and painful.
I would recommend studying up a good textbook and find some quality example code. The key thing is to learn the patterns that make all this stuff hang together correctly and elegantly (well, as much as possible). A good debugger will also really help and get familiar with the standard C libraries too.
You may notice your applications crashing at the drop of a hat initially but perservere as C is definitely worth at least dabbling in. You will understand some of the amazing abstractions higher level languages provide and what is really going on under the hood.
We need more homebrew developers. I am a GBA/NDS and many other embedded platform developer and hope to see that you continue with this. I would say skip to arm assembler and then back up to C or any other language you like, once you know how the processor works, languages are just syntax.
I assume your prior experience covers the programming mindset, breaking things down into bite sized chunks and then writing code to perform those chunks. Then another module that links those together and so on. Then C is just another language, a very very simple language, no need to dive into the corners of it, drive down the middle. It is a good habit to declare variables, etc, and here you will have to. The compilers will tell you when you have forgotten something. You are not going to need big concepts, big structures, language magic, this is embedded, you are resource limited, write some bytes here, read a register there, extract a bit from the data to see if a button has been pressed, write a register in response to move a sprite, etc.
I think you will find the NDS much harder than C at first, there are two processors and some infrastructure to get the simplest of working binaries. Granted there are many many examples out there as well. I generally (and still do) recommend starting with the GBA then graduate to the NDS. bite size chunks.
A lot of things from OOP is the same or almost the same in PHP and C#.
You don't play with pointers in C# (compared to C++) so I would definitely recommend going with C# if you want to play with C.
What C are you talking about?
C#
foreach(string item in itemsCollection)
{
...
}
PHP
foreach($itemsCollection as $key=>$value)
{
...
}
etc.
I like C# because it is strongly typed and your types are automatically checked while you write a code... The possibility of trying to save integer into string or vice versa is zero compared to PHP where you can save anything into anything...
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
Coming from a OO background (C#/java) I'm looking for resources to learn how to design pure C programs well.
Whilst i'm familiar with the syntax of C, and i can write small programs, i'm unsure of the approach to take for larger applications, and what techniques to employ. Anything you guys can recommend.
EDIT: I'm happy to completly abandon OO for the purposes of programming in C, my interest is in learning how to structure a program without OO, I want to learn about good ways of designing programs in procedural languages such as C.
This posting has a list of UNIX books which includes most of the classic C/Unix works. For C programming on Windows, Petzold's Programming Windows is probably the best start.
For C program design, some of the UNIX programming books will tell you snippets but I'm not aware of a 'C program architecture' book.
If you're used to java, some tips for C programming are:
Make use of stack. Often when you call a procedure you will want to have variables allocated in the caller's stack frame and pass pointers to them into the procedure you want to call. This will be substantially faster than dynamically allocating memory with malloc() and much less error-prone. Do this wherever appropriate.
C doesn't do garbage collection, so dynamically allocating data items is more fiddly and you have to keep track of them to make sure they get freed. Variables allocated on the stack (see 1) are more 'idiomatic' where they are applicable. Plus, you don't have to free them - this is a bonus for local variables.
Apropos of (2), consider an architecture where your functions return a status or error code and pass data in and out using the stack as per (1).
Get to know what setjmp() and longjmp() do. They can be quite useful for generic error handler mechanisms in lieu of structured exception handling functionality.
C does not support exceptions. See (3).
Lint is your friend. Splint is even friendlier.
Learn what the preprocessor does and what you shouldn't do with it even if you can.
Learn the ins and outs of endian-ness, word alignment, pointer arithmetic and other low-level architectural arcana. Contrary to popular opinion these are not rocket science. If you're feeling keen, try dabbling in assembly language and get a working knowledge of that. It will do much for your understanding of what's going on in your C program.
C has no concept of module scope, so plan your use of includes, prototype declarations, and use of extern and static to make private scopes and import identifiers.
GUI programming in C is tedious on all platforms.
Apropos of (10) learn the C API of at least one scripting language such as Tcl, Lua or Python. In many cases, the best use of C is as a core high-performance engine on an application that is substantially written in something else.
The equivalent of a constructor is an initializing function where you pass in a pointer to the item you want set up. Often you can see this in the form of a call to the function that looks like setup_foo(&my_foo). It's better to separate allocation from initialising, as you can use this function to initialise an item you have allocated on the stack. A similar principle applies to destructors.
Most people find Hungarian notation about as readable as written Hungarian. The exception to this is native Hungarian speakers, who typically find Hungarian notation about as legible as Cuneiform.. Unfortunately, Hungarian notation is widely encountered in Windows software and the entire Win32 API uses it, with the expected effects on the legibility of software written on this platform.
C/Unix books, even really good ones like the ones written by the late W Richard Stevens tend to be available secondhand quite cheaply through Amazon marketplace. In no particular order, get a copy of K&R, Stevens APUE and UNP 1 & 2, the Dragon book, Rochkind, Programming Pearls, Petzold and Richter (if working on Windows) and any of the other classic C/Unix works. Read, scribble on them with a pencil and generally interact with the books.
There are many, many good C/Unix programming resources on the web.
Read and understand the Ten Commandments of C Programming and some of the meta-discussion as to the why's and wherefores behind the commandments. This is showing its age to a certain extent, although most of it is still relevant and obscure compilers are still quite common in the embedded systems world.
Lex and Yacc are your friend if you want to write parsers.
As Navicore points out below (+1), Hanson's 'C Interfaces and Implementations' is a run-down on interface/implementation design for modular architecture with a bunch of examples. I have actually heard of this book and heard good things about it, although I can't claim to have read it. Aside from the C idioms that I've described above, this concept is arguably the core of good procedural design. In fact, other procedural languages such as Modula-2 actually make this concept explicit in their design. This might be the closest thing to a 'C Program Architecture' book in print.
Read the C FAQ.
My concerns going from OO back to C were addressed in David Hanson's "C Interfaces and Implementations".
C Interfaces and Implementations
Seriously, its approach made a huge difference in avoiding accidentally building the large ball of yarn that many non-oo systems wind up as.
Here's some interesting responses from a different question regarding OO programming in C. I made a post about some C code I worked with which basically impelmented object orientation stopping just short by not including virtual methods.
If I were doing C coding, I would use this technique to define 'objects'.
I find keeping Design Patterns in mind is always helpful, and can be implemented in most languages.
Here's a nice PDF discussing object oriented C programming.
While it is written as a somewhat language-agnostic text, Code Complete provides a lot of good guidance on code structure and organization, along with construction practices.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
After The C Programming Language by Brian Kernighan and Dennis Ritchie, some of the books most favoured by beginners turn out to be ones best avoided, such as anything by Herb Schildt or even the O'Reilly Practical C Programming, and there doesn't seem to be much alternative to these. Otherwise most of the material available is about C++.
Besides K&R and the excellent C: A Reference Manual which I have already, what other books are the best to use for learning to code in C, (plain C89 and not C++), without learning bad practices along the way?
Peter van der Linden's Expert C Programming: Deep C Secrets
C: A Reference Manual by Harbison and Steele
It's not a tutorial book, but it's hands-down the best book on C (even over K&R in my opinion). Used in conjunction with K&R (or any other tutorial), you'll get a great foundation in C.
This explains why Schildt is bad. Some more criticism here.
Search SO for C resources.
I would be tempted to read Practice of Programming and Programming Pearls. Both are quite terse books and C orientated
K&R essentially covers everything you need to know about C, and even implements a few data structures that are commonly used. If you're using *nix and want to learn how to take advantage of the operating system, Advanced Programming in the UNIX Environment, Third Edition is a good reference/guide to common uses such as reading a file, creating threads, etc. Sample code is in C.
I'd say to eschew the books entirely. Pick a project, any project (although not too large), and implement it in C. There's no substitute for simply jumping in and doing it. K&R gives enough knowledge that you can begin stumbling along and gaining the experience that makes for true good learning.
I like Pointers on C by Kenneth A. Reek. I won't do so far as to say it's better than K&R but I certainly found it more friendly and easier to learn from. I started with K&R, but didn't really get a hang of C until I picked up this book.
Edit: I also just found out that the price of this book has skyrocketed since I bought it. So while my recommendation still stands as such, I cannot really recommend it at the current asking price. So if you can find a used copy or a copy at a library then it's worth getting, but at its current price there are other books that are basically just as good for a lot less money.
Expert C Programming is book I consider worth at least looking through once you've gotten the hang of C, although I'm hesitant to outright recommend it. On the plus side it contains a number of good tips and tricks and some very useful advice. On the minus side those tricks and pieces of advice are badly organize, buried among not so useful advice and half the book seems filled with lame jokes, asides and irrelevant (but occasionally amusing) stories. So I'd borrow it from the library, but not pay money for it.
But as you no doubt realize, you'll never really learn C until you write C.
Pick up your K&R book again, and this time do the exercises. Then compare your code with the code in K&R and see if it has similar elegance in the function interfaces and data structures. This isn't a book to read through quickly and go to the next book. It contains a lot of valuable information, and the exercises will help you to realize some of them that you probably missed on the first reading.
C unleashed.
Beginning C by Ivor Horton (3rd edition) from APress is a great introductory book on C programming. This book is very thorough and is not a reference book but a good tutorial from start to end on everything in the C language.
Beginning C by Ivor Horton (3rd Edition)
A great book to learn C is:
C BY DISSECTION The Essentials of C Programming by Al Kelley & Ira Pohl
Very easy to read wth lots of great programming examples.
The best textbook on C I have is C: A Software Engineering Approach by Peter A. Darnell and Philip E. Margolis. While it is (undeservedly) not as famous as other books, I found it very readable and it handles all the details K&R skips over.
It has two disadvantages though:
It is from 1996, so it does not cover C99. (This should be fine with you since you are interested in C89.)
It is quite expensive.
Edit:
Another book of interest is C Programming FAQs by Steve Summit. While I don't have this book in print, the accompanying web site helped me a lot in understanding the less obvious features of C.
I might also recommend reading C programs. Sadly I haven't done enough of this myself to recommend particular ones.
There are some brief but helpful reviews at (the Russian mirror of) the ACCU, for beginner's C and for advanced C.