Best Practices for Programming in C 123
An anonymous reader writes "Although the C language has been around for close to 30 years, its appeal has not yet worn off. It continues to attract a large number of people who must develop new skills for writing new applications, or for porting or maintaining existing applications. This article provides a set of guidelines that can help you with your coding."
I wish C were that popular! (Score:4, Interesting)
I'm sure that in some ways that statement may be true, but I've been trying for MONTHS to get people interested in the C/C++ Meetups! [meetup.com] Compared to Python [meetup.com] you'd think we were trying to start a Sanskrit [americansanskrit.com] study group!
btw..fp? hee hee!
Maybe It's Just A Cultural Thing (Score:2)
Maybe C coders just don't cotton to "meetups". Maybe newer languages are more likely to give rise to such things. Mayber newer technologies give rise to such things. Trying to have a C "meetup" today might be a lot like trying to re-create the Homebrew Computer Club or Woodstock.
Of course hardware hacking and Jimi Hendrix music still attract a lot of people. They just don't attract them in the same way.
Re:I wish C were that popular! (Score:1)
The King is dead. Long live the King!
This is the way it always is. Established, dead, boring... You do your work with it but don't get emotional about it. Newer tech, newer languages - these attract a certain personality type that tends to be more passionate about evangilizing and promotion.
Looks like the author also knows VB (Score:2, Informative)
for(i=0 to 100)
array[i]=0
Maybe I missed something but since when is that C?
Re:Looks like the author also knows VB (Score:2)
For i = 0 To 100
array(i) = 0
Next
Brain fart, I suppose.
Re:Looks like the author also knows VB (Score:2)
In VB, you need:
Next i
Re:Looks like the author also knows VB (Score:1)
Re:Looks like the author also knows VB (Score:5, Informative)
Re:Looks like the author also knows VB (Score:3, Funny)
I wish that the code i'm debugging had... (Score:1, Funny)
Whitespace
Write in C (Score:4, Funny)
ah, filks... (Score:5, Informative)
scanf replacement? (Score:2, Interesting)
Re:scanf replacement? (Score:2)
Re:scanf replacement? (Score:3)
ack! no way!
use strtol, strtoll, strtoul, strtoull, strtof, strtod, and/or strtold. they're much better functions. all of them except strtol, strtoul and strtod are relatively recent additions, though, so you might want to stick to those 3 for now.
Re:scanf replacement? (Score:1)
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf( "atoi( \"1\" ) = %d\n", atoi("1") );
printf( "atoi( \"-1\" ) = %d\n", atoi( "-1" ) );
printf( "atoi( \"0\" ) = %d\n", atoi( "0" ) );
printf( "atoi( \"foo\" ) = %d\n", atoi( "foo" ) );
}
and the resulting output:
atoi( "1" ) = 1
atoi( "-1" ) = -1
atoi( "0" ) = 0
atoi( "foo" ) = 0
Not exactly what you want. btw if I had a be
atoi is a bad idea, too much undefined behavior (Score:1)
(For C++ heads, just read an int from a stream of whatever kind with >>, just as you do for any other type, and then check the stream status afterwards to make sure the operation succeeded, as in if (mystream >> myint) it_succeeded(); )
Re:scanf replacement? (Score:2, Informative)
You should always check the return value from any functions in the scanf family against the number of items whose value you want to set. That will tell you whether or not you've r
Re:scanf replacement? (Score:1)
fscanf can be used in a safe manner in conjunction with sprintf to dynamically format and constrain the input buffer length. See the following code snippet:
char inbuf[80], format[10];
// do stuff
sprintf(format,"%%%ds", sizeof(inbuf)-1);
if (fscanf(fp, format, inbuf)!=EOF)
See "The practice of programming" by Kernighan and Pike, for more details.
Re:scanf replacement? (Score:2)
Other people just want you to bootstrap your machine with a paperclip.
Re:scanf replacement? (Score:2)
Better site (Score:5, Funny)
Re:Better site (Score:1)
Best Practice 0 (Score:1, Insightful)
Dont programm in C unless you have a really good reason to.
Good reasons are:
In all other cases, use a high-l
Re:Best Practice 0 (Score:1, Interesting)
Real C programmers never think "never program in language unless you have to".
Real C programmers think "I can make any new computer language under the sun in C, so why should I switch from C in the first place
"(void *)(void *);"
Higher and Higher (Score:3, Insightful)
Consider C++: you can screw up in all the ways you can screw up with C, and many more besides. I don't think anybody would consider C++ a low-level language.
I actually agree with your point. I'd just express it differently: C supports the kind of
Re:Higher and Higher (Score:2)
Re:Higher and Higher (Score:2)
I don't think you can have a meaningful definition of "high-level" that doesn't include everything more advanced that assembly language. And once you're past that point, I don't think you can go around insisting that Language X is or is not "more high level" than Language Y. If you try, you just end up with a simplistic assertion that isn't very us
Re:Higher and Higher (Score:2)
For example, it's extremely good at doing all sorts of things with tables of function pointers and sets of functions that take the sa
Re:Higher and Higher (Score:2)
Nothing new (Score:4, Insightful)
1. Indent properly.
2. Make your code readable.
3. Use good variable names.
4. Avoid buffer overflows.
5. Avoid using statements like goto.
They missed the most basic rule of them all though, convert to C++.
Re:Nothing new (Score:5, Funny)
Ahem...
1. Indent properly.
2. Make Your code readable.
3. Use_good_variable_names.
4. Avoid buffer *overflows.
5. for (;;x = "Avoid using statements like goto.") {;}
Re:Nothing new (Score:2)
Better yet, convert to a language that doesn't have every wart from C plus some tumors of its own. Why settle for moving to a different piece of the swamp when you can climb onto dry land?
Re:Nothing new (Score:2)
Because no-one's found dry land yet? :-)
(Yes, there exist languages that are technically superior to C++ and/or have stronger underlying programming models, but none of them yet has the critical mass of users and support, particularly libraries, that C++ has, without compromising some other way.)
Re:Nothing new (Score:2)
When a goto is safe, readable and tidy then you should use a goto.
Re:Nothing new (Score:1)
1. Write your code as if the person maintaining it is a homicidal maniac who knows where you live. All else is commentary.
Obfuscated Error (Score:2, Insightful)
peephole (Score:3, Informative)
FYI, the article seems to be something like a company "basic C coding standards" rather than anything to do with what I understand as "best practices"; maybe a coding tips sheet for an introductory C programming class.
Larry
I agree, and was it wrong about NULL? (Score:1)
struct _x {
int a;
int b;
}
it was legal to say &(((struct _x *)NULL)->b)
to figure out the offset of b within the structure?
So I agree, it seems like pretty basic tips, not any sort of "best practices" thing.
- adam
Re:I agree, and was it wrong about NULL? (Score:4, Informative)
The compiler may be able to do it; you can not, as it involves dereferencing a null pointer, which makes it undefined according to the C Standard.
You should use the offsetof macro that the Standard supplies, which your compiler may or may not define as (similar to) the construct you're attempting to use.
You'd use
offsetof( struct _x, b )
add apply it to an instance of struct _x as:
#include <stddef.h>
void doit( struct _x* ix ) {
int i = offsetof( struct _x, b )
int b = *(int*)( ( (char*)ix ) + i ) ;
int* bp = (int*)( ( (char*)ix ) + i )
}
Re:peephole (Score:3, Interesting)
From what I've seen in industry there are plenty of PHB's that need to read things like this. I've had PHB's argue that "Everything should be a global variable" because it "makes everything easier." Real businesses need to hear things like this... if it comes from IBM someone just might l
use good libraries (Score:5, Informative)
For example, for the C program that I'm writing right now, I decided to use GLib [gtk.org] -- the base utillity library used by GTK. [gtk.org]
I initially chose it for portability reasons, but soon discovered it had a wealth of cool stuff in it. In addition to providing the standard data structures (trees, hashes, linked lists), it also has a string type ( GString, [gnome.org] ) which handles a lot of the string issues that C programmers get bogged down with.
A lot of the gotchas (buffer overflows, et. al.) mentioned in this article have to do with these string issues, and using GLib's GString data type has enabled me to avoid those.
There is another library similar to GLib, The Apache Portable Runtime, [apache.org] used in the Apache webserver, and also in Subversion. [tigris.org]
In addition to all this, I'm using XML as the storage format for my program, mostly because libxml [xmlsoft.org] takes care of the file parsing issues so I don't have to.
Bottom line, choose your libraries carefully, they can make a world of difference.
Thomas
Re:use good libraries (Score:1, Informative)
GString? (Score:2)
G-String?? Could they have come up with a different name for that type of string? Issues like butt-flossing and the like..
Re:use good libraries (Score:2)
Re:use good libraries (Score:1)
Re:use good libraries (Score:2)
More Tips! (Score:5, Funny)
- When you've learned all there is to know about C, find out how to simplify it a bit in C++. Notice the job security and look of awe when you master the ++.
- After mucking around in these low-density languages, step up to Perl and see how a language built by a task-oriented person stomps one built by a system-oriented person. See your project file sizes shrink before your very eyes!
- Now take your newfound magic ability to learn new languages and apply it to whipping out pages with PHP and MySQL for all your friends quickly! You'll be the talk of the C crawlers crowd! Hey! Gimmie some content! Aw, forget it - let me just play!
- Now plumb the depths of (supposed) machine-independent laguanges by writing some Java and finding out what "Sun-certified" means! (hint: Sun owns it)
- Optional: Head back to school to get a PhD in autoprogramming theory and self-construction methods. Sequester yourself away to your dorm room for endless hours of experiments training a neural net to convert tasks to code using the most efficient method possible.
- Finally, wrap up your technical life by examining all these related language nuances holistically and achieve the zen of programming: "there is no language"
Re:More Tips! (Score:1)
Re:More Tips! (Score:2)
Nice satire. Unfortunately, I think a lot of Slashdotters will take it (especially the second bullet) seriously.
Re:More Tips! (Score:2)
Satirical, but well paid nonetheless. ;-)
The article is all good, but... (Score:2)
I've got Lakos' book, but there just isn't much out there on non-trivial stuff.
How about articles that show intelligent uses of CVS, Doxygen, and autotools?
What about using C++, boost.python, mod_python, and apache for that killer website?
Re:The article is all good, but... (Score:2)
open to non-members, though membership is
cheap and includes journals covering C,
C++ and related languages as well as tools,
techniques, and more.
Re:The article is all good, but... (Score:2)
CVS: OReilly: Essential CVS, CVS Pocket Reference
C++: Addison Wesley: Effective C++, More Effective C++, C++ Gotchas
Mod_Python, Apache: each have multiple o'reilly books
Boost.python, doxygen: small use solutions in a bigger pool. Notably, for doxygen, you should consider looking into literate programming.
As far as books that are *really* about setting up a project in an intelligent way, try design patterns, fowler's refactoring, co
Using continue in place of the null statement? (Score:3, Interesting)
This could be rewritten as:
I believe this is clearer, and less error prone.Re:Using continue in place of the null statement? (Score:5, Insightful)
IMO every loop should have brackets, and every 'if' statement too, even when not strictly necessary. They're as good as extra whitespace for visually separating chunks of code, and there's absolutely no downside to including them. I've never understood why many C programmers are so resistant to the idea of extra brackets.
Re:Using continue in place of the null statement? (Score:1)
into
rather than
Re:Using continue in place of the null statement? (Score:1)
back in 99 a while after i started using c/c++ i was on a 50 hours spree to get a "demo" done. (check www.scene.org for the definition of demo)
it all looked fine and i sent the stuff away, then when viewing the demo on the bigscreen for the actual competition they had to select a special graphics mode that made the bug visible.
it was just the typical if () blabla; moreblabla; that wasn't in curlys and that piece of code was a boun
Re:Using continue in place of the null statement? (Score:3, Informative)
[pedantic]
They are braces, not "curly brackets", let alone "brackets".
These things have perfectly good names.
() parentheses
[] brackets
{} braces
[/pedantic]
Re:Using continue in place of the null statement? (Score:1)
Re:Using continue in place of the null statement? (Score:2)
Ted Nelson corrected me about not using these names, in 1979.
But what do you call the ">" in a preprocessor #include statement? "Angle brackets" is what I have heard them called...
Re:Using continue in place of the null statement? (Score:3, Funny)
I prefer
while (*dest++ = *src++) malloc(1000);
Re:Using continue in place of the null statement? (Score:2)
Is:
clearer than:
I don't agree -- because of the idiom factor. Yes, the first is clearer to those who don't yet know C. But I believe the latter is clearer to experienced C programmers.
Interestingly, a moderator
Just like UNIX! (Score:4, Insightful)
UNIX is the same age, and it hasn't stopped people from thinking that UNIX-like operating systems are the pinnacle of good design.
They're already written (Score:2)
Rob Pike: Notes on Programming in C (Score:2, Insightful)
Idiosyncratic (and some Wrong) Notes on ... (Score:3, Informative)
I note that Pike doesn't even come close to labeling his piece "Best Practice For C Coding" - for which I thank him.
He does have points that are at least arguably valid, but he lost me at the end.
"Include files should never include files" ?! Pure bull-freaking-crap hogwash. Rather the opposite is the case! Every include file should include every dependency
Re:Idiosyncratic (and some Wrong) Notes on ... (Score:1)
I never say I agree with all his points. He is not a god, and he never pretends to be one.
OTOH, Henry Spencer ...
Best practice of C programming (Score:1)
Origin of that awful phrase "best practices?" (Score:2)
Does it mean ANYTHING different from"recommendations?"
Does anyone ever give any evidence that the "best practices" are actually best?
Re:Origin of that awful phrase "best practices?" (Score:1)
See Business Case for Better Software Practices [stevemcconnell.com] from Professional Software Development (2nd Edition of After the Gold Rush).
Re:Best practice? Don't use it! (Score:4, Insightful)
But for embeded systems, where your resources may be very limited, wouldn't a good optimizing compiler do a better job than an OO one?
I'm sure an assembly code monkey could do better than a c junkie, but I wouldn't know the rankings between the compiled code now-a-days as a desktop programmer.
Re:Best practice? Don't use it! (Score:3, Interesting)
I've read many times that modern compiled C code or well written C++ code is typically far better than hand written assembly code. I don't know that definitively, however. I'd assume that for small snippets, like specific loops etc., that an assembly programmer could still look at the compiler output and perhaps improve it slightly (if they could understand it!).
C++ is a super-set of C, so in theory you can get the same output if you want. However, typically program efficiency is at a higher level than
Re:Best practice? Don't use it! (Score:3, Interesting)
Ah.. but with
Re:Best practice? Don't use it! (Score:3, Informative)
When writing C++ you have full control over the use of dynamic type info, static or polymorphic method lookup, memory use and object lifetime, etc.
So, a good programmer can ensure that for performance critical code, none of those expensive features are used (selectively).
Re:Best practice? Don't use it! (Score:2, Insightful)
In the old days, many CPUs were simple, they only concerned themselves with the current instruction. And, with their lower speeds, compiler optimizations were too slow (and required too much memory) to be worth it. These days, it's not an issue.
Re:Best practice? Don't use it! (Score:2, Informative)
Argh! No it isn't! If C++ were a superset, all valid C programs would be valid C++ programs. This is obvious tripe.
Presumably, this doesn't compile with your C++ compiler.
Re:Best practice? Don't use it! (Score:2, Insightful)
C++ is effectively a super-set of C, though not a strict superset of C.
Good enough for you?
Re:Best practice? Don't use it! (Score:1)
Re:Best practice? Don't use it! (Score:2, Informative)
Re:Best practice? Don't use it! (Score:2)
Relative performance of asm/C/C++ (Score:2)
Possibly, but he'd have to be a very good monkey. Many instruction sets and processor architectures are so complex now that writing things the "intuitive" way in assembler does not yield the optimal result. It takes a lot of specialist knowledge to get a good assembly implementation of non-trivial algorithms on such systems, and the best place fo
Re:Best practice? Don't use it! (Score:5, Insightful)
Re:Best practice? Don't use it! (Score:2)
About every language except C and C++ (including some that are more "enabling" than "restrictive") effectively prevent code injection by buffer overflows and format string errors, which make for a significant portion of exploits. Of course, a system is not automatically safe if you get rid of these problems, but scince logic or algorithmic errors (or plain stupidity :-) are possible in C as well, you can only
Re:Best practice? Don't use it! (Score:3, Insightful)
Re:Best practice? Don't use it! (Score:2)
1) Code that works
2) Code that doesn't work
3) Code that endangers my computer
If Java can eliminate the bottom class, more power to it. If a program doesn't work, you don't use it. If a program is unsafe, you may get screwed before you figure out not to use it. Again, which is the real danger here?
Re:Best practice? Don't use it! (Score:2)
Re:Best practice? Don't use it! (Score:1)
some_func( (void (*)(void*))x );
I would rather say that C allows you to do some pretty complex things than to say C is complex. While there is the obfusicated C coding contest which will show you much worse (complex?) code, it is not that the language is at fault.
C is really quite simple. The number of keywords is few, the syntax is not terribley difficult. I'd rather think of C like legos, very simple, but powerful enough to build awesome creations.
Re:Best practice? Don't use it! (Score:2)
IMO it isn't. Assembly is trivially easy to write. But assemblers have gotten progressively crappier over the years, as much more development effort has been put into C compilers. Even popular assemblers like NASM are barely passable compared to what could be done.
Re:Best practice? Don't use it! (Score:2)
It depends on the cpu architecture.
For a neat learning experience, try programming the Texas Instruments C6701 family of VLIW DSP's [ti.com]. 8 different execution units allowing you to specifically designate 8 instructions to execute in parallel - depending on the instruction type - 'flying' registers, manually specified wait states - NOP takes a parameter! Multiple busses, 256 bit wide program memory, etc, etc. The TI tools include an 'Optimizing Assembler' which is totally
Re:Best practice? Don't use it! (Score:2)
Re:Best practice? Don't use it! (Score:1)
perhaps you and I should form a PAC on this subject!
so true.
And the funny part is this does not prevent memory mismanagement.
Re:Best practice? Don't use it! (Score:2, Interesting)
OTOH, Best practice? Don't use overkill languages (Score:4, Insightful)
Now, why on earth would I do something like that? Just to piss off the comp sci types around me? Well, no, but that's a nice side effect.
Reasons I love/use C:
- It IS glorified assembly. As such, the compiler tries to be minimally helpful and just lets me do what I want to do.
- It doesn't allow OOP crap. I won't argue that OOP doesn't have its place, somewhere, but that place isn't in anything I've needed to build yet.
Why do I hate OOP so much? First and foremost I find it only a tool of obfuscation in the stuff I write. It's much easier to debug procedural code by just following the execution path than wondering what the hell the object that was just instantiated invoked in the constructor, etc. Too much jumping around in the code - basically causes me to forget to look, because it's not intuitive. Same exact reason I hate FORTH (but I'm still fluent in it anyway). I'd rather just have an initializer function called immediately following the declaration of a new variable than having behaviours tacked on.
- C is faster than C++ if you do everything according to the OOP model that C++ leads you toward. I guarantee my pointer math blows away any "safer" solution in terms of raw speed. It's also just as safe, because all the inputs are bounds checked once so I know they can't exceed certain limits. However, for intelligent mixes of OOP-model code and C-style fun, there's no significant speed difference.
- Also, C is standard. C is everywhere. I can use it (with code appropriate to the task) on everything from a PIC12xxx series part clear up to our IBM big iron (though that lack of curly braces it quite annoying). As long as I hang out close to ANSI, my code tends to be very portable. As such, I have a library that is used on everything from small, embedded M68k-series processors up to 16-proc Unix boxes and even larger yet mainframes. Completely threadsafe, no memory leaks, and very, very portable.
Basically, don't use bloat-o-language unless you have a good reason. Remember - CPUs still essentially execute one instruction at a time, mostly in order. Programming is all about moving register 1 to register 2, possibly while performing an arithmetic operation involving register 3.
I would assert that inappropriate use of OOP model programming, a complete disregard for effeciency in the face of beauty-of-design, and an unholy fascination with language du jour has lead to the sorry, bloated, buggy, slow state of modern applications. IMHO, OOP has lead us down this path, without buying us much. Much except the ability to hire less competent programmers to build their tiny chunk of the application, because everything's overdesigned and all the interfaces are pre-specified, because that's how humans would model the problem. Usually there's little regard for how a machine could best handle the problem.
Re:OTOH, Best practice? Don't use overkill languag (Score:3, Informative)
And processing of large data volumes in a fairly straight forward manner is also very good to do in straight and "simple" code. And C is really good for that. (I'm think eg cryto code, which is both quite math intensive and highly sequential.)
I won't comment on your views on OOP, while I don't agree with them I don't think anything good will come
Re:Best practice? Don't use it! (Score:3, Informative)
Well, let's pretend you didn't mean to start a "better language" war, and address your points.
Don't even get me started on the 'C is faster than C++ myth'. Only in the hands of an idiot.
MYTH??? Bring it on, Java-boy. Pick any CPU intensive task, and my C code will DESTROY your best Java code for speed.
Java does have its uses, including decent type checking and memory management, as you mentioned. Those carry a cost, however. You don't get something for n
Best Practice, Avoid Dynamic Memory (Score:2)
Everyone defends higher level things like Java, C# and other scripting languages on the basis that we should have tons of little dynamically allocated little objects floating around, and that you need to have a beefy memory manager floating around to deal with it.
Why do you have to have tons of tiny objects floating around? All that tiny little allocating over and over again just slows everything down, and probably makes your programs more complex. I say, screw dynamic allocation, just use big virtual me
Re:the best practice (Score:3, Funny)
right? (Score:2)
But code that sucks *should* be righted...
Re:the best practice (Score:2)