Why does the use of strictly conforming programs and conforming implementations not ensure absolute portability?

Viewed 222

C11, 4. Conformance, footnote 5 (emphasis added):

Strictly conforming programs are intended to be maximally portable among conforming implementations.

Why does the combination of strictly conforming programs && conforming implementations lead to a gradation of portability (i.e. maximally)?

In other words, why does the combination of strictly conforming programs && conforming implementations not lead to absolute portability?

What are the obstacles / challenges to ensure absolute portability?

3 Answers

The C standard covers both hosted and freestanding implementations. There is (and could be) no "absolute portability" between the two. For hosted implementations in particular, strict compliance guarantees portability, per the same Conformance section (C11 4.5-6):

  1. 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.

  2. The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to [...]


[ EDIT ] As pointed out by @Nate Eldredge in comments below, the statement that a conforming (hosted) implementation "shall accept any strictly conforming program" does not amount to a guarantee that it will "be able to translate and execute" the same strictly conforming program.

This is because the 5.2.4 Environmental Limits section lists a number of minimum limits, but only requires that "the implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits".

In other words, even if a strictly conforming program follows 4.5 and does "not exceed any minimum implementation limit", there is still no guarantee by the letter of the C law that the implementation will be able to succesfully compile and run it. As @Jerry Coffin put it in this answer to a related question: "a "hello world" program isn't strictly conforming".

Or, as Derek M. Jones commented in The New C Standard:

The topic of a perverse implementation, one that can successfully translate a single program containing all of these limits but no other program, crops up from time to time. Although of theoretical interest, this discussion is of little practical interest, because writing a translator that only handled a single program would probably require more effort than writing one that handled programs in general.

Maximal portability should be understood as a conservative wording. A strictly conformant program should have the same observable behaviour on any conformant implementation.

Yet the portability may not be absolute because some implementations can be wrong for some specific parts of the standard. An example would be optional parts where specific constants should be declared if the option is/is not implemented. And the option is or is not there, but the constant is not... Or an implementation can be mixed version conformant: it is fully conformant only to a very old version of the standard and almost conformant to last version except for some details. Or a defect regarding the standard exists and has not yet been fixed. Unfortunately many real world implementations fall in those categories, so the nice program that should work fine on every conformant implementation still has problem on a commonly used implementation.

Because different implementations are used for different purposes, and target different platforms with different abilities, any attempt to identify a category of programs that all implementations would be required to process meaningfully would either need to exclude all programs that perform jobs which some implementations would be incapable of doing, or brand as non-conforming implementations that would be suitable for many but not all of the tasks for which people use the C programming language.

The authors of the Standard recognized that the most practical solution to this problem was to recognize that people seeking to design quality implementations for many platforms and purposes would seek to process usefully a wider range of programs than required by the Standard, and treat support for such programs as a Quality of Implementation issue outside the Standard's jurisdiction. Unfortunately, the authors of C89 and all later version of the Standard deliberately avoided expressing such intention in any way that might suggest that some C implementations are inferior to others for many purposes.

A solution to this problem, if it wouldn't be politically untenable, would be for the Standard to specify means by which programs can indicate anything special they might need from implementations, and specify that (1) conforming implementations may reject any program for any reason, though quality implementations shouldn't do so needlessly, and (2) implementations MUST, as a condition of conformance, reject any programs which they could not otherwise process in conforming fashion. That would make it possible to have a category of programs whose meaning would be defined on all platforms (even though on some platforms there might not exist any implementations that could process them), but which could still exploit abilities that are not universally supportable. Unfortunately, I know of no way by which the Standard could be steered in that direction.

Related