declaration of variable in for loop

P

poornimamprabhu

Hi there,

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?
 
W

Walter Roberson

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}
When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

The answer is compiler dependant. C does not define when or where
memory allocation is made for automatic variables: it only
defines rules for when storage is meaningfully accessible, and
rules about which declaration of a name is the one denoted by
a mention of the name.

In some compilers the answer would be "neither of the above".
For example some compilers allocate automatic variables from
a heap, so the fact that the variable showed up with a particular
address in each iteration could just reflect the fact that no
unreleased heap allocations were made between iterations of the loop.
 
D

DDD

Hi there,

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}

}

When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

because each for loop execution is considered as separte block. And
the memory address of K should be random.
 
S

santosh

Hi there,

suppose i have piece of code like

Include stdio.h here.

int main(void) is better form.
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);

You probably want:

printf("%d\t%p = %d\n", i, (void *)&k, k);

The 'p' format specifier expects a void * value and the type of the
value yielded by the address-of operator is "pointer to T" where T is
the type of it's operand. Also the '*' character in your format string
specifies that the following formatting operation be of the minimum
field width specified by the corresponding argument to '*'. In this
case it is the fourth printf() argument and thus, the final 'd'
specifier is left without an argument, invoking undefined behaviour.
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

This is implementation dependant. You cannot rely on the address of 'k'
being the same across iterations. However the compiler is very likely
to "optimise" in such cases and create and destroy 'k' only once for
the entire duration of the loop. But you cannot rely on such behaviour.
 
M

Mark Bluemel

Hi there,

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.

I don't understand what you mean by "once at a time"
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

Who knows? More importantly, who cares?

1) The compiler's optimisation routines could have determined
that there was no need for k to be in the nested block and
moved it out
2) The management of memory at run time could (very likely would,
I suspect) mean that the same address was allocated each time
through the loop
3) There may be some other explanation

None of this behaviour is guaranteed by the standard, and it is
far from certain that it would be the same in another environment.

Why are you bothered about how the compiler has organised things?
 
K

Kaz Kylheku

Hi there,

suppose i have  piece of code like
main()
{
        int i,j;
        for(i=0;i<10;i++){
                        int k = i;
                        printf("%d    %p = *%d\n",i,&k,k);
        }

}

When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

There is also this possibility: the address of k was produced only
because you asked for it with the & operator, and the existence of
this address doesn't prove that the value of k is actually ever stored
there.
 
K

Kelsey Bjarnason

because each for loop execution is considered as separte block. And the
memory address of K should be random.

Why? There's no reason - as far as I can tell from the standard - to
expect that it _will_ have a random address, just that it _can_.

The optimizer may have found that each iteration does the equivalent of
"jump over N bytes, leaving that space to hold k", which is a waste of
time in this code - move it out of the loop and the loop will run faster,
the code can't tell the difference and the address won't change.
 
J

jacob navia

Hi there,

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.

For some compilers like lcc-win this is the case.
lcc-win allocates all local variables of the function, no
matter what scope, at the start of the function. The stack is not
modified within the function. This is done for obvious
performance reasons. Imagine that at the end of the
block the stack was adjusted, and at the start space
for the variable would be created. This would make for
at least 2 instructions per block iteration... not a good
idea.

Of course, the *scope* of the variable is ONLY within the
enclosing block. After the block is left, there is no way to access
that stack position within C, unless you take
the address of the local variable.

main()
{
int i,j, *pint;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
pint=&i;
}
*pint = 789; // Accessing illegal storage
}

This would work on lcc-win since the storage is still valid.
I would not do this since it is absolutely non portable.
Other compilers could implement other strategies.

For instance
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


The second "k" could be aliased by the compiler to the first one
and stored at the same memory location.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

For lcc-win it is the second.
 
S

santosh

jacob navia wrote:

main()
{
int i,j, *pint;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
pint=&i;
}
*pint = 789; // Accessing illegal storage
}

This would work on lcc-win since the storage is still valid.
I would not do this since it is absolutely non portable.
Other compilers could implement other strategies.

I hope as a QoI issue lcc-win issues a diagnostic for such uses?

<snip>
 
M

Mark L Pappin

Kaz Kylheku said:
On Jan 30, 10:25 pm, (e-mail address removed) wrote:

[%p takes a 'void*' and '&k' isn't one]
There is also this possibility: the address of k was produced only
because you asked for it with the & operator, and the existence of
this address doesn't prove that the value of k is actually ever stored
there.

In the case that the programmer examines 'k', is the implementation
permitted to behave as if 'k' does _not_ contain the value of 'i'?

mlp
 
M

Mark L Pappin

jacob navia said:
main()
{
int i,j, *pint;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
pint=&i;
}
*pint = 789; // Accessing illegal storage

What's illegal about it?

If the last statement inside the loop body had instead been
pint=&k;
then you might have a point.

mlp
 
J

jacob navia

Mark said:
What's illegal about it?

If the last statement inside the loop body had instead been
pint=&k;
then you might have a point.

mlp

Yes, I mistyped the name of the variable

Thanks
 
W

Walter Roberson

(e-mail address removed) wrote:
You probably want:
printf("%d\t%p = %d\n", i, (void *)&k, k);
Also the '*' character in your format string
specifies that the following formatting operation be of the minimum
field width specified by the corresponding argument to '*'. In this
case it is the fourth printf() argument and thus, the final 'd'
specifier is left without an argument, invoking undefined behaviour.

That only applies if the * follows the %. Outside of a % specifier,
an * represents the literal character '*'.
 
A

Army1987

poornimamprabhu said:
Hi there,

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.
The compiler *is* allowed to place k in a different place each time, but,
why should it?
 
W

Willem

santosh wrote:
) You probably want:
)
) printf("%d\t%p = %d\n", i, (void *)&k, k);
)
) The 'p' format specifier expects a void * value and the type of the
) value yielded by the address-of operator is "pointer to T" where T is
) the type of it's operand.

Aren't casts to and from (void *) automatic ?

) Also the '*' character in your format string
) specifies that the following formatting operation be of the minimum
) field width specified by the corresponding argument to '*'.

Only if the * is between the % and the d.

) This is implementation dependant. You cannot rely on the address of 'k'
) being the same across iterations. However the compiler is very likely
) to "optimise" in such cases and create and destroy 'k' only once for
) the entire duration of the loop. But you cannot rely on such behaviour.

The optimizer may even decide not to create or destroy k at all, when
it realises it's always equal to i, and at the printf call just insert
a seemingly valid value for the %p.

Have you looked at the assembly output for your loop ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
F

Flash Gordon

santosh wrote, On 31/01/08 09:49:
jacob navia wrote:



I hope as a QoI issue lcc-win issues a diagnostic for such uses?

I'm assuming you misread Jacob's code as saying "pint=&k" which is what
he intended (as noted in a subsequent post). If so then I would not
expect a diagnostic although I would be pleased if the compiler produced
one.
 
F

Flash Gordon

Walter Roberson wrote, On 31/01/08 17:45:
No, not when passing a parameter to a function.

You mean not always when passed in all positions to a function. The
following fragment is valid assuming stdio.h has been included.
void *fred = "fred is at %p\n";
printf(fred,fred);
This is valid because the prototype for printf specifies that the first
parameters is of type const char *.

The following, on the other hand, is invalid
char *derf = "derf is at %p\n";
printf(derf,derf);
This is invalid because the prototype for printf does not specify the
type of the second (or subsequent) parameter, so the rules of C specify
that no conversion takes place. Change the %p to a %s and it becomes valid.
 
K

Keith Thompson

suppose i have piece of code like
main()
{
int i,j;
for(i=0;i<10;i++){
int k = i;
printf("%d %p = *%d\n",i,&k,k);
}
}


When i see the address of K its same in all iterations.That means K is
only defined once at a time.
Is it because each for loop execution is considered as separte
block,its allocating in the same address?
or is it allocated memory only once?

The name "k" refers to a distinct object for each iteration of the
loop. Conceptually, that object is created on entry to the block (the
"{") and destroyed on exit from the block (the "}"). Though there are
going to be 10 logically distinct objects, only one of them will exist
at any particular time. Similarly, if this code were inside a
function other than main, the variables "i" and "j" would exist only
while that function is executing. (The same thing applies to main,
but the concept is easier to understand if you consider a more
ordinary function.)

That's what the C language requires. It doesn't specify exactly what
a particular implementation must do to meet this requirement.

There are several ways to do this. Many, perhaps most,
implementations use a contiguous hardware stack for allocation of
local variables. In such an implementation, *either* shared space for
all instances of "k" is allocated on entry to the function, *or* space
for "k" is allocated and deallocated on each iteration of the loop.
In both cases, all instances of "k" are likely to have the same
address. This is just a consequence of the most natural way to
implement what the language requires; it is not itself required by the
language, and you should not depend on it.

For example, some implementations might allocate local storage on a
"heap", where successive allocations are not necessarily consecutive
in memory. In such an implementation, *if* "k" is allocated
separately each time the block is executed, then it could easily have
a different address on each iteration.

In any case, if you stick to what the language guarantees it's not
easy even to check whether all 10 "k"s have the same address. As soon
as "k" goes out of scope, even looking at its address without
dereferencing it invokes undefined behavior. You can, as you did,
display the address with printf and "%p", but the resulting text
string is implementation-defined, and it's not clear how much
information you can *portably* get out of it.

The best answer is just not to worry about it. Know that the compiler
will do what the standard requires it to do (unless it's buggy, which
does happen). If you're curious about how it does this, that's great;
curiosity is A Good Thing. But if your program actually depends on
the details, either you're doing something wrong or you're doing
something subtle and implementation-specific; in the latter rare case,
you'd better know exactly what you're doing.

(Somebody else in this thread already told you about the need to use
(void*)&k rather than just &k with the "%p" format. A couple of other
quibbles that aren't relevant to your question: use "int main(void)"
rather than "main()", and be sure you have a "#include <stdio.h>" at
the top of your program. You might be able to get away with "main()"
and without "#include <stdio.h>", but do it right anyway.)
 
J

Jack Klein

Kaz Kylheku said:
On Jan 30, 10:25 pm, (e-mail address removed) wrote:

[%p takes a 'void*' and '&k' isn't one]
There is also this possibility: the address of k was produced only
because you asked for it with the & operator, and the existence of
this address doesn't prove that the value of k is actually ever stored
there.

In the case that the programmer examines 'k', is the implementation
permitted to behave as if 'k' does _not_ contain the value of 'i'?

No, it can't behave that way. It must behave "as if" 'k' exists and
is written to and read from as specified by the source code, in any
way that effects the output of the program.

But a sufficiently clever compiler could deduce:

1. The address of 'i' is not taken.

2. The address and value of 'k' are both taken in one and only one
place.

3. The value of 'k' will not be changed by the printf() function,
even though that function is passed a pointer to 'k'. It can "know"
this because printf() is a standard library function and such behavior
is mandated for it.

4. At the one and only one place where and address and value of 'k'
are taken, the value of 'k' is always equal to 'i'.

....and that sufficiently clever compiler could then pass the address
of 'i' as the second variable argument to printf(), and the value of
'i' as the third. 'k' does not actually need to exist at all.

No output produced by this program could tell.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top