Yes, an implementation can place arbitrary restrictions on the programs that it can process, although they still match the letter of the standard. But the goal of 5.2.4.1 is that the easiest way to meet your specific requirements is to maintain reasonable limits for all programs.
You can create one program that will process each of the translation limits defined in 5.2.4.1 (and this, for example, does not produce any output), and then write a “compiler” that recognizes this single program and creates an executable file that does equivalent to int main(void){}
, rejecting every other program with a diagnostic message saying that it exceeds the implementation translation limits.
Such a compiler, of course, would be completely useless, so (as far as I know) no one bothered to create such a thing. (I thought about doing it myself, just for that.)
In practice, compiler developers want to create useful compilers that will correctly compile real C code.
Requirements 5.2.4.1 are designed in such a way that the easiest way to satisfy them (if you are writing a useful C compiler) is to impose as few actual limits as possible.
For example, the corresponding compiler should support 127 levels of nesting blocks for this mythical "one program." The easiest way to satisfy this requirement is to maintain arbitrary depth of nested blocks if the compiler uses dynamic data structures. In practice, the depth is not limited by the hard limit in the compiler source, but by the amount of memory available at compile time. (Or the compiler could use some internal fixed-size data structure that allows for exactly 127 levels, but it is probably easier to resolve dynamic sizes.)
You might think that it would be better if the standard imposed more “reasonable” requirements, so that the appropriate compiler should accept all programs that do not exceed certain specified limits. The problem is that such “reasonable” limits are extremely difficult to pinpoint. There will always be some programs that exceed the capabilities of the compiler - and the size or complexity of such programs depends on the internal data structures and algorithms used by the compiler, and on the ability of the particular system in which the compiler runs on. The standard could not cover such details or foresee what limitations might be “reasonable” for future systems.
source share