C Programming

From Ggl's wiki

Jump to: navigation, search

Contents

Techniques

Writing a Program, is writing a text

If you want to write code for the machine, please write in machine code :). In the beginning of computer programming, developers had no choice. After they wrote language that where more understandable for human and more efficient for some tasks.

When you write code, you write a text that will be read either by you either by other developer. You may remember all the tricks and all the signification of the variables and functions at the time you write the code. However will it be the case in 6 month when someont will ask you to debug it ?

Thus you will probably want to write clear code. Code that people understand. Clear does not mean heavy and verbose writing style. It means simple, concise and explicit. As when you talk to someone, you don't want her to misunderstand what you say or you promise. It's the same when you write code. You need to be explicit in order to ensure that people can expect the write behavior from you code.

Constant variables

You cannot corrupt what you cannot modify.

Function pointers

They are a way to implement polymorphism in C:

typedef int (*function_t)(char *, const char *, int);

Encapsulation

Encapsulation provides access to data and state through an unique interface. It abstracts the data representation from the user and allows the developer to change the implementation details without change for the user. It is a core principle to reduce the impact of change.

Assertive programming

Assertive programming means you assert a certain condition is true, otherwise you abort the program. C provides a standard interface through <assert.h> and the function assert(). Assertive programming is commonly use to check value at a function entry and exit. The function checks its arguments are sane (no NULL pointer, no out of bound intergers, etc...) as well as the variables it has modified. It is close to programming by contract where a the caller and the callee must respect a contract that defines the input and the output.

Checking arguments at runtime may induce overhead. Furthermore some checks are not relevant once the program is considered correct. assert() is actually a macro. The compiler flag (CFLAGS) NDEBUG disable it. However sometimes, either you want to keep some checks, either you want more complex checks. libnana may provide the features you want. Its scopes goes beyond assertive programming as it also provides custom logging and debugging functions and macros. Let stay in assertive programming. The I() family of macros provides optimized assertations and custom facilities.

Why a assertion abort when the condition is false ? A assertion helps to ensure program consistency. A variable can hold correct values, incorrect values and insane values. What I call insane values here, is values that you don't expect in the program. A common example is NULL pointer. If you pass a NULL pointer to a function, something wrong happened before. Then the process runtime is not consistent. You probably don't have means to recover or check the whole state for inconsistencies. In this case, the almost always best solution is to abort.

As the C is a weakly typed programming language, it is hard to statically detect these inconsistencies at compile time. In object oriented language, helped by static typing, you can enforce object consistency by always instanciating correct object in the constructor. Then once the object is correct, the type system ensures corrects objects are always passed between functions. However as functions or methods can modify the object, they may introduce incorrect values or inconsistencies. Programming by contract helps to keep objects consistent by checking the correctness of each modification.

Explicit Code Path

References

  • The Development of the C Language by Dennis M. Richie (one of the original developers).
  • The Elements of Programming Style Principles extracted from The Elements of Programming Style by B. Kernighan and P.J. Plauger
  • Notes on Programming in C by Rob Pike. Comments on specific topic of The Elements of Programming Style.
  • Programming Design in the UNIX Environment by Rob Pike and Brian Kernighan. Sometimes subtitled "cat -v considered harmful", this paper shows why commands in the UNIX environment should be orthogonal and only do one thing well. If someone wants more feature she should pipes commands to achieve the expected result instead of extending a existing command. In the paper, they took the example of cat -v that asks cat to print (-v for "make visible") non-printable characters as an anti-pattern of the unix way. Instead they advise to write a command vis that takes as input the output of cat (or another command) and replace non-printable characters either by nothing or by a character. The paper is not limited to this example, and I found it very inspirational.
  • How To Design A Good API and Why it Matters by Joshua Bloch. Some guidelines on API design. Not C specific but also useful in C.
  • EWD249: Notes on Structured Programming by Edsger W. Dijkstra