I did not know that was legal

R

Roedy Green

I have using Intellij. One thing it often does in make suggestions on
how to improve your code. One it made, I thought was illegal till I
tried it out.


If you have code like this:

case 1:
int x = expression;
break;
case 2:
x = expression;
break;

that is LEGAL even though program flow does not flow through the
definition. You DON'T have to promote x out of the switch. You can
think of it that it works AS IF you always fell through each case. The
key to this mystery is understanding that local variables are not
actually allocated where you define them. They all get allocated at
once when you enter the method by reserving N stack slots, where they
effectively became extra dummy parameters to your method.
 
P

paul

I have using Intellij. One thing it often does in make suggestions on
how to improve your code. One it made, I thought was illegal till I
tried it out.


If you have code like this:

case 1:
int x = expression;
break;
case 2:
x = expression;
break;

that is LEGAL

It might be legal, but does it really *improve* your code??

Paul
 
T

Thomas Fritsch

Roedy said:
If you have code like this:

case 1:
int x = expression;
break;
case 2:
x = expression;
break;

that is LEGAL even though program flow does not flow through the
definition. You DON'T have to promote x out of the switch.
A way to write it a little less irritating is:

switch (...) {
int x;
case 1:
x = expression;
break;
case 2:
x = expression;
break;
}
 
T

Timo Stamm

Roedy said:
The
key to this mystery is understanding that local variables are not
actually allocated where you define them. They all get allocated at
once when you enter the method

It's not per method, but per block:

{
int x = 0;
}
x = 3; // unknown variable



Timo
 
D

Daniel Dyer

I have using Intellij. One thing it often does in make suggestions on
how to improve your code. One it made, I thought was illegal till I
tried it out.


If you have code like this:

case 1:
int x = expression;
break;
case 2:
x = expression;
break;

that is LEGAL even though program flow does not flow through the
definition. You DON'T have to promote x out of the switch. You can
think of it that it works AS IF you always fell through each case. The
key to this mystery is understanding that local variables are not
actually allocated where you define them. They all get allocated at
once when you enter the method by reserving N stack slots, where they
effectively became extra dummy parameters to your method.

It doesn't work if you put curly brackets around your case code like this,
which is how I prefer to write my switches:

case 1:
{
int x = expression;
break;
}
case 2:
{
x = expression;
break;
}


Dan.
 
R

Roedy Green

It might be legal, but does it really *improve* your code??

That is debatable, but in does have the effect of narrowing the scope
of a variable, which is general is a good thing. I mention this not
to advocate strange looking code, but so that you will believe you
eyes when you see it.
 
J

Jeffrey Schwab

Daniel said:
It doesn't work if you put curly brackets around your case code like
this, which is how I prefer to write my switches:

case 1:
{
int x = expression;
break;
}
case 2:
{
x = expression;
break;
}

Those don't seem to be the same x.

javac Main.java
Main.java:13: cannot find symbol
symbol : variable x
location: class Main
x = expression;
^
Main.java:18: cannot find symbol
symbol : variable x
location: class Main
System.out.println(x);
^
2 errors

---------------------------------------------

class Main {
public static void main(String[] args) {
int expression = 42;

switch(2) {
case 1:
{
int x = expression;
break;
}
case 2:
{
x = expression;
break;
}
}

System.out.println(x);

}
}
 
R

Roedy Green

It's not per method, but per block:

{
int x = 0;
}
x = 3; // unknown variable



Timo

From my reading the JVM virtual machine spec, that is not correct.
they are all allocated slots on method entry. The compiler could share
slots when it is safe, but the actual allocation is done as part of
the call to set up the stack frame which sets the base for allocating
parameters and local variables all on the stack. When you call any
method you push parameters for it, then its return address and jump
the method. It then allocates its locals by bumping the stack pointer
up enough slots to leave room.

The only time this causes serious trouble is in recursion, because you
get a multiplier effect for every bit of padding in the local
variables.

At the JVM level, the type of each variable in a local slot is fixed.
You could not use the slot for a reference then recycle it as an int.
Of course AOT or Hotspot can do that sort of optimisation so long as
the next effect is the same.
 
R

Roedy Green

Those don't seem to be the same x.

in that "case" you have logically two different local variables named
x.


case 1:
{
int x = expression;
break;
}
case 2:
{
int x = expression;
break;
}

which is most of the time what you intend. You doing similar little
calculations for each case. x is local to each case.

By the way, for you Pascal programmers, those {} have no speed
penalty. They are purely for explaining your scope. No new block gets
allocated.

the JVM is very simple minded. local variables are numbered slot
numbers. If you allocated them on the fly, the compiler would need to
track stack depth. Not that hard, but then the slot number would
change depending no how many temporaries were on the stack. That would
complicate low level debugging. So Sun allocated all locals up front
so they could have fixed slot numbers.
 
T

Timo Stamm

Jeffrey said:
Those don't seem to be the same x.

I think that was Daniels point. The curly brackets define a new block.
So the local variables are only visible within each block.


Timo
 
R

Roedy Green

I think that was Daniels point. The curly brackets define a new block.
So the local variables are only visible within each block.

I think the point got lost that the code would not compile with the
{}.
 
M

Mike Schilling

Roedy Green said:
From my reading the JVM virtual machine spec, that is not correct.
they are all allocated slots on method entry.

But that's not really relevant. The key to your mystery is that the scope
of a local variable (that is, the places where it can be used) is from its
declaration to the end of its enclosing block, and case statements don't
begin new blocks.
 
A

Andy Dingley

That is debatable, but in does have the effect of narrowing the scope
of a variable, which is general is a good thing.

It doesn't (AIUI). The scope of the variable is defined by the blocks
that contain it, not quite the literal execution path that the switch
might suggest. Declaring inside the switches is both unclear and not
even restricting the scope any further than you could do by declaring it
just outside the switch.

If I wantd to have code like this, I'd write Perl.
 
M

Mike Schilling

Andy Dingley said:
It doesn't (AIUI). The scope of the variable is defined by the blocks
that contain it, not quite the literal execution path that the switch
might suggest. Declaring inside the switches is both unclear and not
even restricting the scope any further than you could do by declaring it
just outside the switch.

This last is not true.

int x
switch (expr)
{
int y;
...
}

// x is still in scope, y is not.
 
T

Tris Orendorff

This last is not true.


By "last" I assume you mean, "Declaring inside the switches is both unclear
and not even restricting the scope any further than you could do by
declaring it just outside the switch."
int x
switch (expr)
{
int y;
...
}

// x is still in scope, y is not.

In your example, y is out of scope because of the block "{}" snd not the
switch statement.
 
M

Mike Schilling

Tris Orendorff said:
By "last" I assume you mean, "Declaring inside the switches is both
unclear
and not even restricting the scope any further than you could do by
declaring it just outside the switch."

Just the part about "not even restricting the scope any further " What's
unclear is largely in the eye of the beholder.

In your example, y is out of scope because of the block "{}" snd not the
switch statement.

A switch statement always controls a block.
 

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,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top