15

I have been going through a bit of history of C, and I find that in earlier versions of C, like in C89 standard, it is mandatory to declare variables at the beginning of a block.

But I also find there are some relaxations from C99 standard specification, where variable can be declared anywhere before it is used.

My question is why the earlier versions made it mandatory? my emphasis is to know if there was any technical difficulties in designing the compiler at those days, that prevented them identifying declarations at any point.

Also, with a compiler design perspective I understand, with such a restriction in C89, it is easy to handle variable declarations and usage with the help of an intermediate file to store the mappings. But are there methods that can handle the case without using an intermediary file, say some memory based storage?.

user207421
  • 305,947
  • 44
  • 307
  • 483
Amrith Krishna
  • 2,768
  • 3
  • 31
  • 65
  • 2
    There's no need for an intermediate file to store the mappings, and there never was. – user253751 Mar 27 '15 at 03:18
  • @immibis - if its not too much trouble, can you elaborate on some of the memory based methods (or any other non file based method). – Amrith Krishna Mar 27 '15 at 03:20
  • Frankly, I greatly prefer languages like Pascal where you *must* declare your variables separately, up-front. It's just a better way to structure code. – FoggyDay Mar 27 '15 at 03:21
  • 2
    @AmrithKrishna You're basically asking how the compiler can use arrays...? – user253751 Mar 27 '15 at 03:23
  • 10
    Close-voters, please think twice before voting to close this as "primarily opinion-based". OP is asking for the technical justification of a piece of the C89 standard. – Pradhan Mar 27 '15 at 03:23
  • It seems to me like it was more of a style enforcement. That variables being declared at the top of their block scope was just good style. – jschultz410 Mar 27 '15 at 03:27
  • 4
    @FpggyDay: you're so wrong it's amazing (minimising the scope of data and code to where it's actually useful - and meaningful values are ready to assign - is a fundamental principle of maintainable programming), and you're increasing the impression that this question should be closed as opinion based by diverting from the technical aspects of the question into a statement of opinion. – Tony Delroy Mar 27 '15 at 03:31
  • 1
    @Pradhan He's asking why Dennis Ritchie made a decision in 1972. Only he knows that, unless it's documented somewhere. – user207421 Mar 27 '15 at 03:52
  • 1
    @EJP I am more interested in the technical considerations that possibly led to such a decision, as I clearly state that emphasis is on understanding the technical difficulties. – Amrith Krishna Mar 27 '15 at 03:56
  • @EJP No, he is asking about a decision in the C89 ANSI standard. It isn't a stretch to imagine that the decisions made were well-documented. It is indeed possible that this was a purely stylistic decision which, at the time it was made, had no supporting technical reasons for either side; however, given that it is a very fundamental aspect, I would be very surprised if this were true. – Pradhan Mar 27 '15 at 03:59
  • 1
    @Pradhan Most of the decisions in the C89 standard were made by Dennis Ritchie in 1972, certainly including this one, and the C89 standard does not contain technical justifications for every language feature. – user207421 Mar 27 '15 at 04:01
  • 1
    @AmrithKrishna Same answer. Ask Dennis Ritchie. – user207421 Mar 27 '15 at 04:02
  • 1
    @EJP Really? I did not know that. I assumed "ANSI Standard" implied there would have been deliberations similar to todays C++ ISO standards. – Pradhan Mar 27 '15 at 04:03
  • 5
    Don't forget, back in the early 1970's when C was first being designed, the machines didn't necessarily have as much as 64 KiB of memory (they had *less*!) in which to work. Simplification was necessary to get the compiler to perform. – Jonathan Leffler Mar 27 '15 at 04:12
  • 1
    @Pradhan: To a very large extent, the C Standard committee took the language as it was, and the library, and made mostly minimal changes to it. The biggest change was function prototypes, which had been extensively tested with C++. Lesser changes were in the definition of the preprocessor and the `#` and `##` operators. They took a subset of the Unix C library and made it standard, but seldom changed the functionality of the functions which were adopted (which is why `gets()` survived until evicted in C11). The least successful features were committee inventions like trigraphs and locales. – Jonathan Leffler Mar 27 '15 at 04:22
  • @JonathanLeffler IIRC mktime was a committee invention. – Random832 Mar 27 '15 at 06:16

2 Answers2

19

If the compiler sees a consolidated list of all the local/automatic variables up front, it can immediately work out the total amount by which to move the stack pointer to reserve stack memory for them - just one operation on the stack pointer. If it handles the variables in dribs and drabs as they're encountered in the function, moving the stack pointer incrementally, then there ends up being more opcodes dedicated to stack setup and stack pointer updates. It's important that the stack pointer be up to date whenever a further function call's performed. Newer compilers do a tiny bit of extra work to patch back in the amount by which to move the stack pointer after all the function's been considered. (I'd hazard that the effort's so minimal that the early Standard was shaped more by the conceptual appeal of knowing what to do up front than the effort of being more flexible, but if you just want to get something working - why make extra efforts?)

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • 4
    The corollary way to think of this is that in the prehistory of computers compiling C89 and before, it would have taken nontrivial user time to pre-parse through every block to find all the locals before going back to start compiling and emitting code, should the compiler have been structured in such a one-pass way. – Ben Zotto Mar 27 '15 at 03:32
  • 2
    Wouldn't you need back patching (or live with the inefficiency of incrementing the stack pointer multiple times within a function) anyway since new variables can still be declared inside of inner blocks? – sepp2k Mar 27 '15 at 03:38
  • @sepp2k: the same kind of optimisation can be applied at the block level rather than the variable level, so you don't have a perfect solution, but it can be dramatically better. (FWIW, my understanding is that some modern compilers derive a "high water mark" from the largest total size of automatic variables in nested scopes throughout the function, and do one stack pointer operation for that amount of memory, so local-scope memory isn't necessarily promptly returned to the stack, but is at least reused by later local scopes). – Tony Delroy Mar 27 '15 at 03:40
  • 1
    @sepp2k It wouldn't be surprising if inner blocks allocated stack memory on entry and released it on exit. – user253751 Mar 27 '15 at 03:41
  • 2
    @immibis what about on a goto? – Random832 Mar 27 '15 at 06:15
  • @Random832 treat it as a return from N blocks and disallow got into a block with newly declared variables – ratchet freak Mar 27 '15 at 09:29
  • 3
    @ratchetfreak: you can't disallow goto into a block with its own declared variables, C89 permits it. A C compiler must deal with goto by considering the "landscape" at the source and target, including stack position and perhaps what variables are in what registers, and make whatever adjustments it needs just before (or less likely, just after) the jump. So `if (something) goto X;` doesn't necessarily end up as a conditional branch opcode targeting X, even if the CPU has one. – Steve Jessop Mar 27 '15 at 09:48
13

C99 Rationale didn't directly explain why it was not permited in C89, but did say it was added in C99 because it was permited in other languages and the it has been found useful.

Rationale for International Standard — Programming Languages — C

§6.2.4 Storage durations of objects

A new feature of C99: C89 requires all declarations in a block to occur before any statements. On the other hand, many languages similar to C (such as Algol 68 and C++) permit declarations and statements to be mixed in an arbitrary manner. This feature has been found to be useful and has been added to C99.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294