modifying a variable twice in a statement (comparison to c)

I

Ivan Novick

Hi,

In C, you are not allowed to modify a variable 2 times in one
statement.

In perl, this code does not complain at all (similar code in C is
illegal).

Can someone varify that this is legal perl syntax?

####################################
#!/usr/bin/perl
use strict;
use warnings;

my $test = 1;

$test = ++$test;

print "$test\n";
####################################

Thanks,
Ivan
http://www.0x4849.net
 
I

Ivan Novick

I don't know the innards of Perl enough to tell you whether that
statement will always result in all versions of Perl and all platforms
in what you expect (BTW, I don't know what you expect the result to be).

Not sure what the result should be, in C it is undefined, that is why
I am asking this question.
On the other hand, why not just a simple

++$test;
Obviously the problem can be solved by changing the code, my question
is about how perl works, not how to solve some specific problem.
 
C

Charlton Wilbur

IN> Obviously the problem can be solved by changing the code, my
IN> question is about how perl works, not how to solve some
IN> specific problem.

The C answer is to consult the Standard.

The Perl answer is the same, except that we don't have a Standard, we
have a reference implementation. Try it and see.

And if you want to be sure how it works, look for what the perldocs
say. If the perldocs don't say anything on the matter, there's no
guarantee it will continue to work that way.

Charlton
 
D

Dave Slayton

Ivan Novick said:
Hi,

In C, you are not allowed to modify a variable 2 times in one
statement.

In perl, this code does not complain at all (similar code in C is
illegal).

Can someone varify that this is legal perl syntax?

####################################
#!/usr/bin/perl
use strict;
use warnings;

my $test = 1;

$test = ++$test;

print "$test\n";
####################################

Thanks,
Ivan
http://www.0x4849.net


Why stop there? Even more fun is available!:

$wheeeee = 5;
$wheeeee = ++($wheeeee = ++($wheeeee = ++$wheeeee));

etc.

:)
 
B

Brian McCauley

In C, you are not allowed to modify a variable 2 times in one
statement.

In perl, this code does not complain at all (similar code in C is
illegal).

Is it? I thought it was just that it's semantics were undefined.
Can someone varify that this is legal perl syntax?

Yes it's perfectly legal _syntax_.
$test = ++$test;

Semnatically it's is probably best considered ambiguous.
 
P

Peter J. Holzer

Is it? I thought it was just that it's semantics were undefined.

Which is the same thing as "illegal" in C. "Undefined behaviour" means
absolutely anything can happen. The compiler may produce some code which
conforms to some people's expectations of what that code should do. It
may produce code which crashes and/or formats the hard disk. It may
abort compilation with an error message. It may send rude emails to your
boss.

hp
 
U

Uri Guttman

PJH> It may send rude emails to your boss.

i know i used a c compiler which did that when i double modified a
variable. could have been an early gcc.

uri
 
B

Ben Bacarisse

Ivan Novick said:
Hi,

In C, you are not allowed to modify a variable 2 times in one
statement.

Small point, but in C you *can* modify a variable multiple times in
one statement. You are not allowed to do that between sequence points
(and a statement end is one place you get a sequence point) but you
can, legally, write:

(x = 1) && ++x;

because && gives you another one.

As has been said, the perldocs refer to multiple modification in one
statement so Perl seems to have adopted a simpler restriction.
 
I

Ivan Novick

Apparently, perldoc perlop provides the answer in this surprisingly
named section:

Auto-increment and Auto-decrement

"++" and "--" work as in C. That is, if placed before a variable, they
increment or decrement the variable by one before returning the value,
and if placed after, increment or decrement after returning the value.

$i = 0; $j = 0;
print $i++; # prints 0
print ++$j; # prints 1

Note that just as in C, Perl doesn't define when the variable is
incremented or decremented. You just know it will be done sometime
before or after the value is returned. This also means that modifying
a variable twice in the same statement will lead to undefined
behaviour.

I would have expected perl to either reject the syntax or accept as
valid.

In C just because it compiles and runs does not mean it conforms to
the standard, but since in Perl the implementation is the standard, it
makes things tricky when certain things that seem to work in the
reference implementation are actually undefined.

I guess perldoc is like a mini language standard, and if its not in
perldoc then you go by what Perl actually does.

Ivan Novick
http://www.0x4849.net
 
J

Jürgen Exner

Ivan said:
I would have expected perl to either reject the syntax or accept as
valid.

Obviously perl accepts the syntax as valid or do you get a syntax error?
In C just because it compiles and runs does not mean it conforms to
the standard,

You are confusing syntax and semantic.

jue
 
U

Uri Guttman

IN> I would have expected perl to either reject the syntax or accept as
IN> valid.

you can't reject the syntax because it is legal syntax. perl accepts it
as valid it is just bad code from a semantic point of view. why do you
keep harping on this? it is also documented to be an undefined situation
as someone quoted the docs on it.

IN> In C just because it compiles and runs does not mean it conforms to
IN> the standard, but since in Perl the implementation is the standard, it
IN> makes things tricky when certain things that seem to work in the
IN> reference implementation are actually undefined.

the perl docs are very good and accurate. did you read the quoted part
which covers this? what about it don't you understand?

IN> I guess perldoc is like a mini language standard, and if its not in
IN> perldoc then you go by what Perl actually does.

that may be true but the difference between what the docs say and what
perl does is very small. and if you have a legitimate discrepency then
report it to p5p. double modification is not one of those and why do you
care so much about it as it is bad coding in all languages (except for
the few that specify behavior for it).

uri
 
C

Charlton Wilbur

UG> and why do you care so much about it as it is bad coding in
UG> all languages (except for the few that specify behavior for
UG> it).

I'd say it's bad coding in general, on the principle that code is
supposed to communicate clearly to the maintainer. Any expression in
which a variable is accessed or modified more than once can be
rewritten so as to express the intent of the programmer clearly and
unambiguously.

Perl golf is another matter entirely; there, all bets are off.

Charlton
 
P

Peter J. Holzer

Jim Gibson ([email protected]) wrote on MMMMCMVI September
MCMXCIII in <URL:;; In article <[email protected]>, Abigail
;;
;; > Jim Gibson ([email protected]) wrote on MMMMCMVI September
;; > MCMXCIII in <URL:;;
;; > ## Or one of my favorite C statements:
;; > ##
;; > ## x = x+++++x;
;; > ##
;; > ## which is valid C syntax, or used to be anyway (try it). This would give
;; >
;; > Not according to Kerninghan and Ritchie (and they should know):
;; >
;; > If the input stream has been separated into tokens up to a
;; > given character, the next token is the longest string of
;; > characters that could constitute a token.
;; >
;; > Brian W. Kerninghan and Dennis M. Ritchie:
;; > "The C Programming Language", 2n ed,
;; > Prentice Hall, 1988. Appendix A2.1, pp 192.
;; >
;;
;; I am not sure how this quoted statement invalidates the C statement
;; above. I had assumed that the statement "x+++++x" was being interpreted
;; as "(x++) + (++x)", but according to the above, perhaps it should be
;; interpreted as "((x++)++) + (x)". That seems to be invalid, as I get
;; "error: invalid lvalue in increment" from "gcc version 4.0.1 (Apple
;; Computer, Inc. build 5363)" for both "x+++++x" and "((x++)++)+(x)".

It's quite simple. According the above statement, 'x+++++x' is parsed as
follows:

Unparsed stream Maximal token Parsed tokens

x+++++x x x
+++++x ++ x ++
+++x ++ x ++ ++
+x + x ++ ++ +
x x x ++ ++ + x

But a compiler will flag a syntax error as soon as it finds 'x ++ ++'.

That's not a syntax error, that's a constraint violation. Syntactically,
'x ++ ++' is a valid postfix-expression:

postfix-expression: postfix-expression ++
postfix-expression: postfix-expression ++ ++
postfix-expression: primary-expression ++ ++
postfix-expression: identifier ++ ++
postfix-expression: x ++ ++

However, it violates the constraint, that the operand of ++ must be an
lvalue. x++ isn't an lvalue, so x++ ++ violates this constraint.
;; Nevertheless, the statement "x+++++x" was compiled without error by
;; every C compiler I tried at the time (mid 90s).

Then you didn't try any C-compiler conforming to ISO-9899-1990. A
constraint violation must be diagnosed.
;; But the above-mentioned gcc compiler gives 5, not 4, for the equivalent:
;;
;; jgibson 92% cat increment.c
;; #include <stdio.h>
;; int main()
;; {
;; int x;
;; x = 1;
;; x = x++ + ++x;
;; printf("x = %d\n", x);
;; }
;; jgibson 93% gcc -o increment increment.c
;; jgibson 94% increment
;; x = 5

That's an interesting result. From looking at the assembler output, the
Compiler obviously does something like this:

"x++"? Ok, that means to take the current value of x, and increment x
later, so transform "x = x++ + ++x" into "x = x + ++x, x = x + 1;"

"++x"? Ok, that means increment x now, and use the new value. So we
transform "x = x + ++x, x = x + 1;" into
"x = x + 1, x = x + x, x = x + 1"

Nice.

hp
 
M

Mirco Wahab

Peter said:
That's an interesting result. From looking at the assembler output, the
Compiler obviously does something like this:

"x++"? Ok, that means to take the current value of x, and increment x
later, so transform "x = x++ + ++x" into "x = x + ++x, x = x + 1;"

"++x"? Ok, that means increment x now, and use the new value. So we
transform "x = x + ++x, x = x + 1;" into
"x = x + 1, x = x + x, x = x + 1"

int x; pushl %ebp
movl %esp, %ebp
subl $36, %esp

x = 1; movl $1, -8(%ebp) # WRITE 1 into [stack] (location for x)

x = x++ + ++x; addl $1, -8(%ebp) # ADD 1 to [stack] (now 2)
movl -8(%ebp), %eax # WRITE [stack] into [register] (copy 2)
addl %eax, -8(%ebp) # ADD [register] to [stack] (now 4)
addl $1, -8(%ebp) # ADD 1 to [stack] (now 5)



Regards

M.
 

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,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top