dvu@prism.gatech.EDU (Dinh Vu) (09/27/89)
Declaration within a loop:
-------------------------
do {
int i;
........ ;
........ ;
........ ;
} while (1);
Is it true that every time through the loop, a new i variable
is declared (more memory allocated ??)? Or the same i variable
is reused... I see something similiar to this in the GNU 'make'
source code. Also, if I run the code above long enough, will it
take all memory. Thanks.
Dinh Vu <dvu@prism.gatech.edu>
barmar@kulla (Barry Margolin) (09/27/89)
In article <2085@hydra.gatech.EDU> dvu@prism.gatech.EDU (Dinh Vu) writes: > do { > int i; > ........ ; > } while (1); >Is it true that every time through the loop, a new i variable >is declared (more memory allocated ??)? Yes, a new i variable is declared. However, at the end of each time through the loop it is "undeclared", so it can be deallocated. Most C implementations will actually use the same memory location (probably on the stack) each time. And since C isn't required to zero automatic variables, it will probably even have the same value as it had in the previous iteration; however, any program that tries to take advantage of this is pretty disgusting, in my opinion. Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (09/27/89)
In article <30174@news.Think.COM>, barmar@kulla (Barry Margolin) writes: | Yes, a new i variable is declared. However, at the end of each time | through the loop it is "undeclared", so it can be deallocated. Most C | implementations will actually use the same memory location (probably | on the stack) each time. Most C compilers allocate space on the stack for this when the procedure is entered. It therefore is not a practical thing to do to save space. The most common use is to correct for having forgotten to declare a variable at the start of a procedure. -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "The world is filled with fools. They blindly follow their so-called 'reason' in the face of the church and common sense. Any fool can see that the world is flat!" - anon
cpcahil@virtech.UUCP (Conor P. Cahill) (09/27/89)
In article <2085@hydra.gatech.EDU>, dvu@prism.gatech.EDU (Dinh Vu) writes: > Is it true that every time through the loop, a new i variable > is declared (more memory allocated ??)? Or the same i variable > is reused... I see something similiar to this in the GNU 'make' > source code. Also, if I run the code above long enough, will it > take all memory. Thanks. The variable i is an automatic variable allocated on the stack at the start of block. It is not re-allocated each time through the loop. This kind of thing can be verified by creating a small source code file and compiling it with the -S flag to get the assembly language. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
cpcahil@virtech.UUCP (Conor P. Cahill) (09/27/89)
In article <30174@news.Think.COM>, barmar@kulla (Barry Margolin) writes: > In article <2085@hydra.gatech.EDU> dvu@prism.gatech.EDU (Dinh Vu) writes: > > do { > > int i; > > ........ ; > > } while (1); > >Is it true that every time through the loop, a new i variable > >is declared (more memory allocated ??)? > > Yes, a new i variable is declared. However, at the end of each time > through the loop it is "undeclared", so it can be deallocated. Most C I disagree. Using the following source code: int main() { int fd; char *p; char t; extern char *ttyname(); int i; for(i=0; i < 10; i++) { char buffer[50]; printf("buffer = 0x%x\n",buffer); } } The following assembly code is generated (using "cc" on 386/ix): .globl main main: jmp .L54 .L53: movl $0,-16(%ebp) /* i = 0 */ jmp .L58 .L59: leal -66(%ebp),%eax /* get address of buffer */ pushl %eax /* put on stack for printf */ pushl $.L60 /* put string on stack */ call printf /* call printf */ addl $8,%esp /* clean stack */ incl -16(%ebp) /* i++ */ .L58: movl $10,%eax /* get 10 for comparison*/ cmpl %eax,-16(%ebp) /* compare i to 10 */ jl .L59 /* I < 10 ? */ .L57: .L52: leave ret .L54: pushl %ebp movl %esp,%ebp subl $68,%esp jmp .L53 .def main; .val .; .scl -1; .endef .data .L60: .byte 0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x3d,0x20,0x30 .byte 0x78,0x25,0x78,0x0a,0x00 Note that at .L54 the data is allocated ONCE and only once. It is not allocated/deallocated for each iteration. This is unoptimized assembler source generated using the -S flag. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
tneff@bfmny0.UU.NET (Tom Neff) (09/27/89)
In article <559@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: > Most C compilers allocate space on the stack for this when the >procedure is entered. It therefore is not a practical thing to do to >save space. For what it's worth AT&T's pcc on V/386 does share reuse stack space among all temp in-block variables. Intel's C compiler does not though. I'm sure there are tons of other examples pro and con. > The most common use is to correct for having forgotten to >declare a variable at the start of a procedure. Here I must disagree. The most common and obvious use of an in-block temp is to restrict scope! Unless one's editor lacks a "move up" command there is no reason to declare a variable locally within a block just because one "forgot" to declare it function-wide! The declaration is as easily added in one place as the other. But it may be quite important to ensure that "i" or "swaptmp" is unheard-of outside the local block. -- Annex Canada now! Free Quebec; raze and depopulate | Tom Neff Ontario; license Inuit-run casinos on the BC shore. | tneff@bfmny0.UU.NET
tim@cayman.amd.com (Tim Olson) (09/28/89)
In article <559@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes: | In article <30174@news.Think.COM>, barmar@kulla (Barry Margolin) writes: | | | Yes, a new i variable is declared. However, at the end of each time | | through the loop it is "undeclared", so it can be deallocated. Most C | | implementations will actually use the same memory location (probably | | on the stack) each time. | | Most C compilers allocate space on the stack for this when the | procedure is entered. It therefore is not a practical thing to do to | save space. The most common use is to correct for having forgotten to | declare a variable at the start of a procedure. But sometimes it is better to declare the variable in the block to limit its scope rather than to make every variable visible to the entire function. For example, say I want to debug a function by printing out a linked list at a certain point. I can say something like: . . #ifdef DEBUG { struct list *p; for (p=my_list; p; p=p->next) printf("\t%d\n",p->value); } #endif and I have limited my changes to one area. -- Tim Olson Advanced Micro Devices (tim@amd.com)
scott@bbxsda.UUCP (Scott Amspoker) (09/28/89)
In article <14743@bfmny0.UU.NET> tneff@bfmny0.UU.NET (Tom Neff) writes: >For what it's worth AT&T's pcc on V/386 does share reuse stack space >among all temp in-block variables. Intel's C compiler does not though. >I'm sure there are tons of other examples pro and con. > This is frequently poorly implmented. I use local variables in procedures mainly to save a little stack space (although I don't do it very often). In the following example: proc() { if (...) { int i; ... } while (...) { int j; ... } } the variables 'i' and 'j' may use the same location on the stack frame. Of course, this is a trivial example. Some compilers, however, simply give all local variables their own location. I don't understand that kind of laziness. -- Scott Amspoker Basis International, Albuquerque, NM (505) 345-5232
djones@megatest.UUCP (Dave Jones) (09/28/89)
From article <27519@amdcad.AMD.COM>, by tim@cayman.amd.com (Tim Olson): ... > > But sometimes it is better to declare the variable in the block to > limit its scope rather than to make every variable visible to the > entire function. Why did you not say, "Always it is better to declare..."? The only reason I can think of not to put variables into the most restrictive scope that will contain them is that dbx has a bug that causes it to give wrong results without complaint or warning if you use the same name in two scopes. There's nothing more sickening than to be confronted by an enemy procedure with a skillion variables declared at the top. Usually they have generic names like, "temp1", and "ptr". Well okay, maybe there's one thing more sickening than that, but I don't see any reason to bring Jerry Lewis into this.
flaps@dgp.toronto.edu (Alan J Rosenthal) (09/28/89)
cpcahil@virtech.UUCP (Conor P. Cahill) writes: >This kind of thing can be verified by creating a small source code file >and compiling it with the -S flag to get the assembly language. This statement is blatantly false (about anything about C). It confuses implementation with definition. To re-use the same variable cell each time through the loop is a valid implementation of deallocating it and reallocating it each time through the loop, because deallocating and allocating are inverse operations. This doesn't mean that the meaning of declaring a variable inside a loop in C is that it is allocated upon function entry. ajr
cpcahil@virtech.UUCP (Conor P. Cahill) (09/28/89)
In article <559@crdos1.crd.ge.COM>, davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes: > Most C compilers allocate space on the stack for this when the > procedure is entered. It therefore is not a practical thing to do to > save space. The most common use is to correct for having forgotten to > declare a variable at the start of a procedure. There are two reasons that I will normally use for justifying variable declarations and neither of them are to save space. The first is #define macros. For example: #define DEBUG(key,msg) {char buf[512];.... } The second is to try to segregate the use of register variables. I'm not too sure this really has an effect in all compilers, but at least it gives it a chance. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
cpcahil@virtech.UUCP (Conor P. Cahill) (09/28/89)
In article <1989Sep27.185904.18985@jarvis.csri.toronto.edu>, flaps@dgp.toronto.edu (Alan J Rosenthal) writes: > This statement is blatantly false (about anything about C). It confuses > implementation with definition. To re-use the same variable cell each time > through the loop is a valid implementation of deallocating it and reallocating > it each time through the loop, because deallocating and allocating are inverse > operations. This doesn't mean that the meaning of declaring a variable inside > a loop in C is that it is allocated upon function entry. I did not say that a variable declared within a loop is allocated upon function entry. I said that it is not re-allocated throughout every iteration of the loop. The variable is "active" throughout the entire lifetime of the loop. However, if the variable is initialized, it will be reinitialized each time through the loop. In thinking about it a bit more since my original response I would have to say that while this may be the behavior in any "sane" implementation, it would not be prudent to have any expectations as to the value stored in the data area through each iteration of the loop. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
plim@hpsgpa.HP.COM (Peter Lim) (09/28/89)
/ hpsgpa:comp.lang.c / tim@cayman.amd.com (Tim Olson) / 3:11 am Sep 28, 1989 / > But sometimes it is better to declare the variable in the block to > limit its scope rather than to make every variable visible to the > entire function. For example, say I want to debug a function by > printing out a linked list at a certain point. I can say something > like: > Well, why don't you do something like adding an extra pair of braces before and after the loop like: { int i; do { . . } while (1); } this should limit the scope of i in the loop and clear the ambiguity of whether i is re-allocated every time round the loop. ** Seem obvious to me. Regards, Peter Lim. HP Singapore IC Design Center.
seanf@sco.COM (Sean Fagan) (09/29/89)
In article <1199@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes: >> Yes, a new i variable is declared. However, at the end of each time >> through the loop it is "undeclared", so it can be deallocated. Most C > >I disagree. Using the following source code: You are also wrong. Since you felt like posting source code, I think I will do the same. What do you expect the following code to do, when compiled and run? static int x = 0; int foo() { return x++; } main() { int a; for (a=0; a< 100; a++) { int b = foo(); printf ("b = %d\n", b); } return (0); } If 'b' is not created each time, then foo() is only called once. However, you will note that it *isn't* called just once. To explain (sort of) the results you got: in the following fragment, for (a=0; a< 100; a++) { int b; } for (a=0; a< 200; a++) { int c; } would you be surprised if &b == &c? I wouldn't; and, in your example, that's what was happening. The compiler knew it could reuse the space, and did so. Did so so well, in fact, that it never touched the stack pointer in-between the loops. Anyway, that's what dmr says, so it must be right 8-). -- Sean Eric Fagan | "Time has little to do with infinity and jelly donuts." seanf@sco.COM | -- Thomas Magnum (Tom Selleck), _Magnum, P.I._ (408) 458-1422 | Any opinions expressed are my own, not my employers'.
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (09/29/89)
In article <3362@scolex.sco.COM>, seanf@sco.COM (Sean Fagan) writes: | main() { | int a; | for (a=0; a< 100; a++) | { | int b = foo(); | printf ("b = %d\n", b); | } | return (0); | } | | If 'b' is not created each time, then foo() is only called once. However, | you will note that it *isn't* called just once. This is logical, but wrong. You are guaranteed that foo() will be called each time through the loop, and that b will be initiallized, but it is an implementation choice if some explicit action which could be identified as "creating" b will be done each time or once. In most existing C compilers (I don't claim all) any explicit action needed is taken once on entry to the procedure. As long as initialization is done each time you can't tell from program behavior if the allocation is done once or many time (not do I see any reason to care). -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "The world is filled with fools. They blindly follow their so-called 'reason' in the face of the church and common sense. Any fool can see that the world is flat!" - anon