Home > Software engineering >  Have the code examples from K&R ever been conforming?
Have the code examples from K&R ever been conforming?

Time:05-19

The C Programming Language by Brian Kernighan and Dennis Ritchie contains a lot of examples such as this famous one (K&R 2nd edition 1.1):

#include <stdio.h>

main()
{
  printf("hello, world\n");
}

Here I note the following issues:

  • No return type.

    Writing functions with no return type was allowed in C90 which the second edition of the book claims to follow. These will default to int in C90. It is invalid C in later versions of the language.

  • No return statement.

    A function with a return type and no return statement was not well-defined in C90. Writing main() with no return being equivalent to return 0; was a feature added in C99.

  • Empty parameter list of main().

    This is valid C still (as of C17) but has always been an obsolescent feature even in C90. (Upcoming C23 talks of finally getting rid of K&R style functions.)


My question:

Was any code in K&R 2nd edition ever a conforming program, in any version of the standard?

CodePudding user response:

No, the programs in the K&R book were never conforming programs 1) (C17 4/7) under any verison of the standard.

  • In C90 (ISO 9899:1990), the code invoked undefined behavior because of the missing return statement.
  • In C99 (ISO 9899:1999) and beyond, the code won't compile because of the implicit int.

Sources below.


Regarding implicit int, one major difference in function return types between C90 and latter versions can be found here:

C90 6.7.1 Function definitions

The return type of a function shall be void or an object type other than array.
/--/
If the declarator includes an idenfifier list, the types of the parameters may be declared in a following declaration list. Any parameter that is not declared has type int.

C17 6.9.1 Function definitions

The return type of a function shall be void or a complete object type other than array type.
/--/
If the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.6.3 for a parameter type list; the resulting type shall be a complete object type.

The main difference being the "complete object type" wording, the definition of complete object type being one of the basic types or a pointer to one (C17 6.2.5). We can conclude that implicit int was allowed in C90 both as the return type or as part of a (non-prototype) parameter list.


Regarding no return statement, this text was always there for general functions:

C90 6.6.6.4

If a return statement without an expression is executed and the value of the function call is used by the caller, the behavior is undefined. Reaching the } that terminates a function is equivalent to executing a return statement without an expression.

C17 6.9.1/12

If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

However, main() is a special case and an exception was added in C99:

C99 5.1.2.2.3

If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0.

Whereas in C90, the equivalent text says:

C90 5.1.2.2.3

A return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined.


Regarding empty parameter lists, it has been marked as obsolescent from C90 to C17. See future language directions, for example C17 6.11 (or C90 6.9, identical text):

6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

6.11.7 Function definitions The use of function definitions with separate parameter identifier and declaration lists (not prototypeformat parameter type and identifier declarators) is an obsolescent feature.

This does however not mean that code using the feature isn't conforming, at least up to ISO 9899:2018. It's simply not recommended practice, and was not recommended practice at the point where K&R 2nd edition was released either.


1) C17 from chp 4:

A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.

A conforming program is one that is acceptable to a conforming implementation.

A strictly conforming program shall use only those features of the language and library specified in this International Standard. It shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior, and shall not exceed any minimum implementation limit.

This means that a conforming program may use features of a conforming implementation that are non-portable, but it may not alter the behavior of a strictly conforming program by for example invoking undefined behavior explicitly listed as such in the standard.

CodePudding user response:

I compiled the program

#include <stdio.h>

main()
{
    printf("hello, world\n");
}

under two well-regarded compilers, gcc and clang. As far as I know both of these compilers would be considered "conforming", and I believe that's one of the things their authors certainly strive for.

Both compilers produced an executable which printed hello, world. Under the definition that

A conforming program is one that is acceptable to a conforming implementation

, I conclude that the program is conforming.

I pass no judgement on the question of whether the program would have been conforming under C89.

Although I have not studied the code examples in K&R2 in some years, I believe that most/all of the rest of them are similarly conforming, despite various pedagogical or other shortcuts which might render them not strictly conforming.

  • Related