Expert C Programming

(Jeff_L) #1

Don't Mix Old and New Styles in Function Declaration and Definition


Never mix the old and new styles of function declaration and definition. If the function has
a K&R-style declaration in the header file, then use K&R syntax in the definition.


int foo(); int foo(a,b) int a; int b; { / ... / }


If the function has an ANSI C prototype, use ANSI C-style syntax in the definition.


int foo(int a, int b); int foo(int a, int b) { /* ...


*/ }


It would have been possible to create a foolproof mechanism for checking function calls across
multiple files. Special magic would be used (as it currently is) on functions like printf that take a
variable number of arguments. This could even have been applied to the existing syntax. All that
would be needed is a constraint in the standard specifying that each call to a function must be
consistent with name, number, and type of parameters and return type in the function definition. The
"prior art" was there, as this is done for the Ada language. It could be done in C too, with an additional
pre-linker pass. Big hint: use lint.


In practice, the ANSI C committee members were quite cautious about extending C—arguably too
cautious. The Rationale shows how they agonized over whether or not they could remove the existing
six-character case-insensitive limitation on the significance of external names. In the end, they decided
they couldn't remove this restriction, somewhat feebly in the view of some language experts. Maybe
the ANSI C committee should have bitten the bullet on this as well, and stipulated a complete solution
even if it needs a pre-linker pass, instead of adopting a cockamamie partial solution from C++ with its
own conventions, syntax, semantics, and limitations.


Getting a Char Without a Carriage Return


One of the first questions that MS-DOS programmers ask on encountering a UNIX system is, "How
do I read characters from the terminal without requiring the user to hit RETURN?" Terminal input in
UNIX is "cooked" by default, meaning that the raw input is first processed so that line-editing
characters (backspace, delete, and so on) can be used, and these keys take effect without being passed
through to the running program. Usually this is a desirable convenience, but it does mean that a read
won't get the data until the user presses RETURN to signify that the line is finished. Input is effectively
line-by-line, whereas some applications need to see each character as each individual key is pressed.


This feature is essential for many kinds of software and is trivial on a PC. The C libraries there
support this, often with a function called kbhit(), which indicates if a character is waiting to be read.

Free download pdf