Please create an account to participate in the Slashdot moderation system

 



Forgot your password?
typodupeerror
×
Programming IT Technology

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."
This discussion has been archived. No new comments can be posted.

Best Practices for Programming in C

Comments Filter:
  • by bluethundr ( 562578 ) * on Thursday July 24, 2003 @10:17AM (#6521937) Homepage Journal
    Although the C language has been around for close to 30 years, its appeal has not yet worn off.

    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 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.

    • I've been trying for MONTHS to get people interested in the C/C++ Meetups! Compared to Python you'd think we were trying to start a Sanskrit study group!

      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.
  • From the article:

    for(i=0 to 100)
    array[i]=0

    Maybe I missed something but since when is that C?
  • Write in C (Score:4, Funny)

    by pauljlucas ( 529435 ) on Thursday July 24, 2003 @10:29AM (#6522096) Homepage Journal
    (Sing this as you would "Let it Be.")
    When I find my code in tons of trouble,
    Friends and colleagues come to me,
    Speaking words of wisdom:
    "Write in C."

    As the deadline fast approaches,
    And bugs are all that I can see,
    Somewhere, someone whispers:
    "Write in C."

    Write in C, Write in C,
    Write in C, oh, Write in C.
    LOGO's dead and buried,
    Write in C.

    I used to write a lot of FORTRAN,
    For science it worked flawlessly.
    Try using it for graphics!
    Write in C.

    If you've just spent nearly 30 hours,
    Debugging some assembly,
    Soon you will be glad to
    Write in C.

    Write in C, Write in C,
    Write in C, yeah, Write in C.
    BASIC's not the answer.
    Write in C.

    Write in C, Write in C
    Write in C, oh, Write in C.
    Pascal won't quite cut it.
    Write in C.

  • scanf replacement? (Score:2, Interesting)

    by ichimunki ( 194887 )
    (please note: I'm still learning C) So what should I be using instead of scanf? The article recommends against it, but doesn't say whether there is a better way to get some input and get interesting chunks out of it.
    • use fget, and then ato[i | f ] #excuse the perl syntax
      • 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.

      • I'm not sure ato[i|f] is the best answer either, consider the following code:

        #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 has undefined behavior for some error conditions. strtol is a safe version. You should only consider using atoi if you are entirely sure that the input is valid. And even then you should choose to use strtol to make the code rubust in the face of changes.

        (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(); )
    • by jguthrie ( 57467 )
      Functions in the scanf family are truly useful, if you can grok them. However, error recovery can be a pain, so it's not generally advisable to use scanf() or fscanf(). Instead, one practice that I use is to read lines into a buffer (using fgets so that you'll be less likely to have a buffer overflow) and then run sscanf on it.

      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

    • 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];
      sprintf(format,"%%%ds", sizeof(inbuf)-1);
      if (fscanf(fp, format, inbuf)!=EOF)
      // do stuff

      See "The practice of programming" by Kernighan and Pike, for more details.

    • Generally, when people suggest that printf/scanf are evil, they're advocating the use of the operator>. Note that these are C++, not C. There are a number of reasons, not the least of which is that they're much more easily guarded regarding insane inputs, and that they're able to handle any type (useful for generic programming.)

      Other people just want you to bootstrap your machine with a paperclip.
      • Actually, it's because they don't have a length specifier, which means that sooner or later you'll get a buffer overflow from some idiot/malicious person giving the program too much input.
  • Better site (Score:5, Funny)

    by fredrikj ( 629833 ) on Thursday July 24, 2003 @10:40AM (#6522236) Homepage
    Here [mindprod.com] is a much better article about coding practices. It also covers broad topics, not just C in specific.
  • Best Practice 0 (Score:1, Insightful)

    by __past__ ( 542467 )
    Wow, that article was really enlightening. *cough* However, here's what I think should be the first item in every "Best Practives for Programming in C" list:

    Dont programm in C unless you have a really good reason to.

    Good reasons are:

    • You are extending an operating system kernel or other huge system that is written in C.
    • You are writing a library and expect it to be used from several other languages. C is the lowest common denominator, every language has a C interface.

    In all other cases, use a high-l

    • Re:Best Practice 0 (Score:1, Interesting)

      by torpor ( 458 )
      Bah! You only say that cause you're probably a crap C programmer.

      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)

      by fm6 ( 162816 )
      Actually, C, or any language that talks in expressions rather than a symbolic representation of machine code, counts as "high level". The problems you mention really have more to do with the design philosophy of C than any lack of sophistication in the language.

      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

      • I don't think anybody would consider C++ a low-level language.
        I'd argue that C++ can be just as low-level a language as C, as long as you disable exceptions and RTTI.
        • So a language that allows you to do low-level things is low level, even if it has lots of high-level features? That's not a definition most people would accept.

          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

          • You're right of course, most languages allow you to do the equivalent of 'system("asm...");' and therefore they can all be as low level as any other, but my point is that not only is it as easy to do low-level stuff in C++ as it is in C (whereas with some other languages, it's not quite so easy), C++ also provides easier ways to code things that would be just as effient in C.

            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

            • OK, I guess I agree with you. C is obsolete except for the specific kinds of programming in your list. I just stick at saying that C is not a "high-level language". Probably doesn't matter, but I pick semantic nits for a living, and even on Slashdot I can't help myself.
  • Nothing new (Score:4, Insightful)

    by McAddress ( 673660 ) on Thursday July 24, 2003 @10:47AM (#6522323)
    This article really does not say anything that any decent programmer does not know. Why we need an article to tell us the basic rules of C is beyond me.

    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++.
    • by zulux ( 112259 ) on Thursday July 24, 2003 @11:47AM (#6522976) Homepage Journal

      Ahem...

      1. Indent properly.
      2. Make Your code readable. //this is a great idea
      3. Use_good_variable_names.
      4. Avoid buffer *overflows.
      5. for (;;x = "Avoid using statements like goto.") {;}

    • They missed the most basic rule of them all though, convert to C++.

      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?

      • 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?

        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.)

    • 6. Be aware that rule number 5 said 'Avoid', and not 'Never'.

      When a goto is safe, readable and tidy then you should use a goto.

    • The real rule in programming is:

      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)

    by wbav ( 223901 )
    Apparently it was too obfuscated for IBM. The first code example is missing a } at the end of the line.
  • peephole (Score:3, Informative)

    by LarryRiedel ( 141315 ) on Thursday July 24, 2003 @10:57AM (#6522424)

    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 thought you could use NULL to calculate structure offsets, so with something like

      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
      • by orthogonal ( 588627 ) on Thursday July 24, 2003 @12:09PM (#6523269) Journal
        I thought you could use NULL to calculate structure offsets, so with something like

        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?



        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 ) ; // or
        int* bp = (int*)( ( (char*)ix ) + i ) ;
        }
    • Re:peephole (Score:3, Interesting)

      by Zarf ( 5735 )
      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.

      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)

    by nthomas ( 10354 ) on Thursday July 24, 2003 @11:06AM (#6522511)
    In addition to the good advice proffered by the article, I should also like to add that using good libraries can make a world of difference.

    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

    • by Anonymous Coward
      Or just use Objective C with NextStep/OpenStep/Cocoa/GnuStep.
    • ...it also has a string type ( GString, ) which handles a lot of the string issues...

      G-String?? Could they have come up with a different name for that type of string? Issues like butt-flossing and the like..
    • Huh huh, you said gstring. Huh, /beavis.
    • I never realized that you could do real object oriented programming in C until I used GTK+. Admittedly, I'm an ameteur programmer who taught myself C by way of C++ (screwy, ain't it?), but with C you can do all your OOP and with GLib, it's not too bad. I just wish there was decent documentation on GObject, which might be a nice idea to me if I know how to use it. From my viewpoint of not being able to use it, though, it seems very overcomplicated. Oh, and libxml is really a great programming library too
  • More Tips! (Score:5, Funny)

    by mugnyte ( 203225 ) * on Thursday July 24, 2003 @11:19AM (#6522657) Journal
    Oh what enlightenment!

    - 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"
  • What I want to see is material on setting up a project in an intelligent way.
    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?
    • http://www.accu.org/, by programmers for programmers. There's even a mailing list
      open to non-members, though membership is
      cheap and includes journals covering C,
      C++ and related languages as well as tools,
      techniques, and more.
    • Um. You might want to look into the o'reilly and addison wesley catalogs.
      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
  • by geoswan ( 316494 ) on Thursday July 24, 2003 @07:34PM (#6527910) Journal
    The null body of a for or while loop should be alone on a line and commented so that it is clear that the null body is intentional and not missing code.
    while (*dest++ = *src++) ; /* VOID */

    This could be rewritten as:

    while (*dest++ = *src++)
    continue;
    I believe this is clearer, and less error prone.
    • by AuraSeer ( 409950 ) on Friday July 25, 2003 @02:38AM (#6530009)
      It's even clearer to use curly brackets, but the article doesn't mention that either.

      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.
      • I completely agree with your curly braces statement. The company I'm working at now specifically states in their "Coding Guidelines" that all loops - normal, empty, one-line - should have braces (also all if statements, try/catch blocks/etc.). This is mainly to allow for easy changes later. You don't end up with the random errors that come in to play when you change

        while(something)
        do something;

        into

        while(something)
        do something;
        and do something else; //oops

        rather than

        while(somethi

        • i totally agree, altho i had to learn that lesson myself the "hard" way :P.

          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
      • I agree with you, but you have invoked a pet peeve of mine.

        [pedantic]

        They are braces, not "curly brackets", let alone "brackets".

        These things have perfectly good names.

        () parentheses
        [] brackets
        {} braces

        [/pedantic]
    • I prefer

      while (*dest++ = *src++) malloc(1000);

  • Just like UNIX! (Score:4, Insightful)

    by Junks Jerzey ( 54586 ) on Friday July 25, 2003 @08:14AM (#6531087)
    Although the C language has been around for close to 30 years, its appeal has not yet worn off

    UNIX is the same age, and it hasn't stopped people from thinking that UNIX-like operating systems are the pinnacle of good design.
  • Buy a copy of "Code Complete". Scrawl "coding standards" on the front in big black marker. Live & breathe it.
  • A classic [lysator.liu.se]
    • Jeeze, there's nothing like taking a bunch of idosyncratic preferences and treating them as best practice, let alone enforcing them at a workplace.

      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
  • I think the best practice of C programming is to use it only when absolutely necessary. Otherwise, use modern language which will boost your productivity and make your applications easier to write and with fewer bugs (and no presence on Bugtraq due to a buffer overflow)
  • Where did it come from?

    Does it mean ANYTHING different from"recommendations?"

    Does anyone ever give any evidence that the "best practices" are actually best?

"Hello again, Peabody here..." -- Mister Peabody

Working...