By definition, any source text or collection thereof which is "accepted" by a Conforming C Implementation is a "Conforming C Program". Because implementations are given broad latitude to extend the language in any way which does not affect the behavior of any Strictly Conforming C Programs, any source text T which would not otherwise be a Conforming C Program could be turned into a Conforming C Program by modifying a Conforming C Implementation so that if it were given program that doesn't match T, it would process it normally, and if fed a copy of T it would behave as though it were fed some other program that it would accept.
While this may seem an absurdly broad definition, it satisfies one of the major goals of the C Standards Committee, which was to ensure that if any existing programs could accomplish a task, the task could be accomplished by a Conforming C Program.
As for whether the programs were Strictly Conforming under C89, that's a bit harder to answer. The Standard says that if execution falls through the end of main()
it will return an Undefined Value to the host environment, and imposes no requirements about the consequence of doing so, which would suggest that such an action would invoke Undefined Behavior. On the other hand, the Standard also imposes no requirements upon what happens if a program returns EXIT_SUCCESS
, nor what happens if it returns EXIT_FAILURE
, nor if it returns some other value. Thus, all such actions could be viewed as invoking Undefined Behavior. On the other hand, viewing things in such fashion would make it impossible for any program which terminates to be Strictly Conforming.
I think the most reasonable way of interpreting the Standard would be to say that a program whose execution falls through the end of main() waives any control it might have had to affect what the execution environment does once it terminates. If all courses of action the host environment could perform after a program exits would be equally acceptable, a program's failure to do anything to influence which course of action is taken would not be a defect.
In considering whether a program that fails to specify a return value, or any program for that matter, is "Strictly Conforming", one cannot merely examine the source text, but must also consider the application requirements. If one needs a program to output the characters x and y once each, in some order, the following would be a strictly conforming program that accomplishes that:
#include <stdio.h>
int outputx(void) { return printf("x"); }
int outputy(void) { return printf("y"); }
int main(void)
{
return outputx() + outputy() && printf("\n") && 0;
}
If, on the other hand, one need a program to output "xy", the above would not be a strictly conforming program for that purpose. Thus, I would say that if the application requirements for some task specify that a program must use its return value to influence the host environment, a program that falls through the end of main would not be a Strictly Conforming C Program to accomplish that task. If, however, such influence over the host environment is not part of the application requirements for a task, then a Strictly Conforming C Program could waive such control.
Citations below:
From N1570 section 4 pararaph 7:
A conforming program is one that is acceptable to a conforming implementation. (*) 5) Strictly conforming programs are intended to be maximally portable among conforming implementations. Conforming programs may depend upon nonportable features of a conforming implementation.
Undefined Behavior is defined in 3.4.3:
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
From the C99 Rationale, talking about the definition of conformance [emphasis original]:
A strictly conforming program is another term for a maximally portable program. The goal is to give the programmer a fighting chance to make powerful C programs that are also highly portable, without seeming to demean perfectly useful C programs that happen not to be portable, thus the adverb strictly.
The fact that a program exits without setting a return value may make it non-portable, but the Standard deliberately avoids "demeaning" non-portable programs by calling them non-conforming.