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?
No, the programs in the K&R book were never conforming programs 1) (C17 4/7) under any verison of the standard.
return
statement.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 typeint
.
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 withint
, a return from the initial call to themain
function is equivalent to calling theexit
function with the value returned by themain
function as its argument; reaching the}
that terminates themain
function returns a value of0
.
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 theexit
function with the value returned by themain
function as its argument. If themain
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.