Hi Monks
This behaviour is there with C/C++ "printf" also. We need to know how the "print" statement (see coments below ) is handling variables & its data. Our code in question is
my $x = 0; print $x, $x++; # Print 10??
All the arguments passed to the "print" is kept in a stack! print will push arguments from right-to-left into the stack. Inthe above case value of $x goes into stack (corresponding to $x++).
After the first "push", $x is incremented and on second "push" new value of $x is pushed. Then it start poping to print. For sure it will pop 1 first and then 0. So it will print 10. A program to demo this can be
#!/usr/bin/perl use strict; my @PRINT_STACK; my $x = 0; push @PRINT_STACK, $x++; print "PRINT_STACK => ( ",@PRINT_STACK, " )\n"; push @PRINT_STACK, $x; print "PRINT_STACK =>( ",join(", ",@PRINT_STACK)," )\n"; print pop @PRINT_STACK; print pop @PRINT_STACK; exit();
Again funny facts :)
my $x = 0; print $x,$x, $x++; # Print 110??
This will print 110 for sure, because the value of $x is NOT changed after first push.
Then what would be
my $x = 0; print $x,$x++, $x++; # Print 210??
In case of "C" it will print 210 as expected. but the output you will get in perl is 201. If I make a table with more $x++ in print, it will be as follows (assuming that initial value of $x is 0 ).
| Print order | O/P in C | O/P in Perl |
|---|---|---|
| $x | 0 | 0 |
| $x,$x++ | 10 | 10 |
| $x,$x,$x++ | 110 | 110 |
| $x,$x++,$x++ | 210 | 201 |
| $x,$x++,$x++,$x++ | 3210 | 3012 |
| $x,$x++,$x++,$x++,$x++ | 43210 | 40123 |
| $x,$x++,$x++,$x++,$x++,$x++ | 543210 | 501234 |
"C" is working as I explained above. Why Perl is behaving differently when we have "$x,$x++,$x++" ? Answer is again stacks.
when there are more than one expressions in same statement, perl uses another stack for evaluating them. ie, it wll push 0 to stack first. Then increments $x to 1. Then again it pushes 1 to stack and increments it to 2. Now all operations are over. Now Perl with pop contents of the operation stack and push to print stack. Then push the last $x. So it will print "201" for
print $x,$x++,$x++Following program will demonstrate the entire thing :)
#!/usr/bin/perl use strict; my @PRINT_STACK; my @OP_STACK; my $x = 0; my $temp; #print $x,$x++,$x++; push @OP_STACK, $x++; # push the l +ast $x++ to the operator stack (pushes 0) print "OP_STACK => ( ",@OP_STACK, " )\n"; push @OP_STACK, $x++; # push the n +ext $x++ operator to the operator stack (pushes 1) print "OP_STACK => ( ",join(", ",@OP_STACK)," )\n"; # All Operations are over $temp = pop @OP_STACK; #pop The ope +rator stack and push it to print stack (pops 1) push @PRINT_STACK, $temp; # pushes 1 print "PRINT_STACK => ( ",join(", ",@PRINT_STACK)," )\n"; $temp = pop @OP_STACK; #pop The ope +rator stack and push it to print stack (pops 0) push @PRINT_STACK, $temp; #pushes 0 print "PRINT_STACK => ( ",join(", ",@PRINT_STACK)," )\n"; push @PRINT_STACK, $x; # push the f +irst $x to the operator stack (pushes 2) print "PRINT_STACK => ( ",join(", ",@PRINT_STACK)," )\n"; print pop @PRINT_STACK; print pop @PRINT_STACK; print pop @PRINT_STACK; exit();
Isn't this a nice hack for obfuscation ?
Comments
Try puting more $x++ for the function call &myprint$x=0; &myprint($x, $x++); sub myprint{ print join ",",@_; }
Cheers!
--VC
UPDATE : I am not sure about all C compilers. I got above behavior with "gcc on FC6 & Turbo C on Windows XP". Also for Perl I tested with "Active Perl On Windows XP & Perl on FC6". I was NOT trying to say Perl & C will behave alike, but I was trying to say that this IS there with most of the implementation of C (gcc on FC6 and turbo C on Windows XP) & Perl (Active Perl On Win XP and perl on FC6). SORRY if misleading.
In reply to Re: print behavior
by atemon
in thread print behavior
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |