'static' value appears to reset after function call [duplicate]Behaviour and Order of evaluation in C#How exactly do static fields work internally?order of evaluation of operandsCan not round trip html format to clipboardList, not lose the reference Why is this Java code 6x faster than the identical C# code?WCF Guid DataMember not Serialized properlyHow to pass a sql connections string value to a C# programC# why object can't be converted to intStatic function returns unexpectedly when called from constructorExit a method back to Main?get set accessors from static Main() - and best practice for boolean storeWidth 100% and height 100% not working in chrome
My mysterious "ruins" wander around and change on their own, what'd be a rational way for them to do that?
What are standard cryptographic assumptions?
Travelling to Spain with a Kosovan passport, what are the outcomes if caught?
Unexpected Code Coverage Reduction
Is there any point in adding more than 6 months' runway in savings instead of investing everything after that?
How to use FDE without needing to share the encryption password
What is my volume?
Does milk make your bones stronger?
Theme or Topic - what's the difference?
Is a Senate trial required after the House impeaches a president?
Find peaks, max and min of an interpolation function?
How to avoid after work hours team dinner?
Prevent sleep if CPU usage is high
Why did a shuttle astronaut have an open book during ascent?
Does flying or hovering make creatures immune to the Earth Tremor spell?
"Chess is 90% tactics" - should a player focus more on tactics in order to improve?
50% portfolio in single stock, JPM - appropriate for 80 year old?
What does the 1.-5. notation mean at the top right corner?
Time machine in Interstellar movie
Was there a clearly identifiable "first computer" to use or demonstrate the use of virtual memory?
What type of rhetorical device is the offering of a source which is really long and not specifying what part of the source is relevant?
What's the link?
Perils of having a moon consisting of valuable material
What is the meaning of Text inside of AMS logo
'static' value appears to reset after function call [duplicate]
Behaviour and Order of evaluation in C#How exactly do static fields work internally?order of evaluation of operandsCan not round trip html format to clipboardList, not lose the reference Why is this Java code 6x faster than the identical C# code?WCF Guid DataMember not Serialized properlyHow to pass a sql connections string value to a C# programC# why object can't be converted to intStatic function returns unexpectedly when called from constructorExit a method back to Main?get set accessors from static Main() - and best practice for boolean storeWidth 100% and height 100% not working in chrome
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1
:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo()
has run, but before the result is subtracted from value
:
But one step later, value
is -1
:
I would expect -8
because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
|
show 10 more comments
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1
:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo()
has run, but before the result is subtracted from value
:
But one step later, value
is -1
:
I would expect -8
because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
9
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
52
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
8
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
14
value -= foo()
is the same asvalue = current value of value (0) - foo() which returns 1
, which is the same asvalue = 0 - 1
.foo()
does decrementvalue
but only after you've referenced it in the calculation that callsfoo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
Jul 23 at 7:43
3
Statements likei += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
Jul 24 at 19:43
|
show 10 more comments
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1
:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo()
has run, but before the result is subtracted from value
:
But one step later, value
is -1
:
I would expect -8
because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1
:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo()
has run, but before the result is subtracted from value
:
But one step later, value
is -1
:
I would expect -8
because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
This question already has answers here:
This question already has answers here:
This question already has answers here:
Behaviour and Order of evaluation in C# [duplicate]
(2 answers)
Behaviour and Order of evaluation in C# [duplicate]
(2 answers)
c#
c#
edited Jul 25 at 22:08
J. Antonio Perez
6,80912 silver badges28 bronze badges
6,80912 silver badges28 bronze badges
asked Jul 23 at 7:24
EmerGEmerG
5226 silver badges11 bronze badges
5226 silver badges11 bronze badges
9
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
52
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
8
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
14
value -= foo()
is the same asvalue = current value of value (0) - foo() which returns 1
, which is the same asvalue = 0 - 1
.foo()
does decrementvalue
but only after you've referenced it in the calculation that callsfoo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
Jul 23 at 7:43
3
Statements likei += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
Jul 24 at 19:43
|
show 10 more comments
9
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
52
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
8
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
14
value -= foo()
is the same asvalue = current value of value (0) - foo() which returns 1
, which is the same asvalue = 0 - 1
.foo()
does decrementvalue
but only after you've referenced it in the calculation that callsfoo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
Jul 23 at 7:43
3
Statements likei += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
Jul 24 at 19:43
9
9
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
52
52
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
8
8
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
14
14
value -= foo()
is the same as value = current value of value (0) - foo() which returns 1
, which is the same as value = 0 - 1
. foo()
does decrement value
but only after you've referenced it in the calculation that calls foo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
Jul 23 at 7:43
value -= foo()
is the same as value = current value of value (0) - foo() which returns 1
, which is the same as value = 0 - 1
. foo()
does decrement value
but only after you've referenced it in the calculation that calls foo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
Jul 23 at 7:43
3
3
Statements like
i += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
Jul 24 at 19:43
Statements like
i += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
Jul 24 at 19:43
|
show 10 more comments
6 Answers
6
active
oldest
votes
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
14
If you changevalue = foo() - value
tovalue = -foo() + value;
in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
Jul 23 at 8:17
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=
is a more complicated thing than may at first appear.
– Norman Gray
Jul 24 at 8:43
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you dovalue
andfoo()
, you get different results. The final addition,a + b
, is commutative, but how you geta
andb
isn't.
– Luaan
Jul 25 at 7:57
6
@AlbertoSantini Because of side effects, it is not.A + B
means first evaluateA
(might cause side effects), keep the result, then evaluateB
(side effects), finally add the results.
– Jeppe Stig Nielsen
Jul 25 at 11:33
|
show 2 more comments
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatinga
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
Jul 24 at 20:22
add a comment
|
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
// end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
// end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
add a comment
|
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo()
, it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment
|
I think it has something to do with how it subtracts value
on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
value
get saved (pushed to the stack) - The
foo()
function returns1
- Now, the
value
is-7
due tofoo()
operation - HERE is the problem: The OLD
value
(which is the one that saved earlier, which is0
) subtracted with1
and the result assigned to the currentvalue
.
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1
, unlike in C.
– Luaan
Jul 25 at 8:04
add a comment
|
value -= foo(); // value = value - foo();
foo()
will return 1
.
value
is initially 0
, so: 0 = 0 - 1
.
Now the value
has -1
.
So the issue is with return 1
.
3
This answer ignores the fact that callingfoo
changesvalue
.
– Theraot
Jul 24 at 10:25
2
@Theraot: This answer is correct; the fact thatfoo
changesvalue
is irrelevant. Regardless of what valuesfoo
changes, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
Jul 25 at 19:14
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
add a comment
|
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
14
If you changevalue = foo() - value
tovalue = -foo() + value;
in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
Jul 23 at 8:17
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=
is a more complicated thing than may at first appear.
– Norman Gray
Jul 24 at 8:43
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you dovalue
andfoo()
, you get different results. The final addition,a + b
, is commutative, but how you geta
andb
isn't.
– Luaan
Jul 25 at 7:57
6
@AlbertoSantini Because of side effects, it is not.A + B
means first evaluateA
(might cause side effects), keep the result, then evaluateB
(side effects), finally add the results.
– Jeppe Stig Nielsen
Jul 25 at 11:33
|
show 2 more comments
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
14
If you changevalue = foo() - value
tovalue = -foo() + value;
in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
Jul 23 at 8:17
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=
is a more complicated thing than may at first appear.
– Norman Gray
Jul 24 at 8:43
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you dovalue
andfoo()
, you get different results. The final addition,a + b
, is commutative, but how you geta
andb
isn't.
– Luaan
Jul 25 at 7:57
6
@AlbertoSantini Because of side effects, it is not.A + B
means first evaluateA
(might cause side effects), keep the result, then evaluateB
(side effects), finally add the results.
– Jeppe Stig Nielsen
Jul 25 at 11:33
|
show 2 more comments
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
edited Jul 25 at 10:30
Peter Mortensen
14.6k19 gold badges89 silver badges118 bronze badges
14.6k19 gold badges89 silver badges118 bronze badges
answered Jul 23 at 8:02
shingoshingo
5,7434 gold badges10 silver badges25 bronze badges
5,7434 gold badges10 silver badges25 bronze badges
14
If you changevalue = foo() - value
tovalue = -foo() + value;
in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
Jul 23 at 8:17
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=
is a more complicated thing than may at first appear.
– Norman Gray
Jul 24 at 8:43
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you dovalue
andfoo()
, you get different results. The final addition,a + b
, is commutative, but how you geta
andb
isn't.
– Luaan
Jul 25 at 7:57
6
@AlbertoSantini Because of side effects, it is not.A + B
means first evaluateA
(might cause side effects), keep the result, then evaluateB
(side effects), finally add the results.
– Jeppe Stig Nielsen
Jul 25 at 11:33
|
show 2 more comments
14
If you changevalue = foo() - value
tovalue = -foo() + value;
in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
Jul 23 at 8:17
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=
is a more complicated thing than may at first appear.
– Norman Gray
Jul 24 at 8:43
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you dovalue
andfoo()
, you get different results. The final addition,a + b
, is commutative, but how you geta
andb
isn't.
– Luaan
Jul 25 at 7:57
6
@AlbertoSantini Because of side effects, it is not.A + B
means first evaluateA
(might cause side effects), keep the result, then evaluateB
(side effects), finally add the results.
– Jeppe Stig Nielsen
Jul 25 at 11:33
14
14
If you change
value = foo() - value
to value = -foo() + value;
in your last sentence you will get the 'expected' result -8
– Eliahu Aaron
Jul 23 at 8:17
If you change
value = foo() - value
to value = -foo() + value;
in your last sentence you will get the 'expected' result -8
– Eliahu Aaron
Jul 23 at 8:17
7
7
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that
-=
is a more complicated thing than may at first appear.– Norman Gray
Jul 24 at 8:43
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that
-=
is a more complicated thing than may at first appear.– Norman Gray
Jul 24 at 8:43
12
12
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
Jul 24 at 9:13
3
3
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you do
value
and foo()
, you get different results. The final addition, a + b
, is commutative, but how you get a
and b
isn't.– Luaan
Jul 25 at 7:57
@AlbertoSantini The addition part is. You don't get an analogue in Maths, since in an immutable world, the problem doesn't exist. It comes from mutability - depending on the order you do
value
and foo()
, you get different results. The final addition, a + b
, is commutative, but how you get a
and b
isn't.– Luaan
Jul 25 at 7:57
6
6
@AlbertoSantini Because of side effects, it is not.
A + B
means first evaluate A
(might cause side effects), keep the result, then evaluate B
(side effects), finally add the results.– Jeppe Stig Nielsen
Jul 25 at 11:33
@AlbertoSantini Because of side effects, it is not.
A + B
means first evaluate A
(might cause side effects), keep the result, then evaluate B
(side effects), finally add the results.– Jeppe Stig Nielsen
Jul 25 at 11:33
|
show 2 more comments
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatinga
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
Jul 24 at 20:22
add a comment
|
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatinga
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
Jul 24 at 20:22
add a comment
|
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1
edited Jul 23 at 7:53
answered Jul 23 at 7:33
BahromBahrom
1,9721 gold badge10 silver badges17 bronze badges
1,9721 gold badge10 silver badges17 bronze badges
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatinga
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
Jul 24 at 20:22
add a comment
|
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatinga
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
Jul 24 at 20:22
11
11
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
Jul 23 at 7:37
16
16
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluating
a
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?– Heinzi
Jul 24 at 20:22
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluating
a
only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?– Heinzi
Jul 24 at 20:22
add a comment
|
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
// end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
// end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
add a comment
|
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
// end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
// end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
add a comment
|
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
// end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
// end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
// end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
// end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
edited Jul 25 at 10:39
Peter Mortensen
14.6k19 gold badges89 silver badges118 bronze badges
14.6k19 gold badges89 silver badges118 bronze badges
answered Jul 23 at 8:18
SᴇMSᴇM
5,6572 gold badges18 silver badges34 bronze badges
5,6572 gold badges18 silver badges34 bronze badges
add a comment
|
add a comment
|
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo()
, it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment
|
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo()
, it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment
|
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo()
, it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo()
, it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
edited Jul 25 at 10:45
Peter Mortensen
14.6k19 gold badges89 silver badges118 bronze badges
14.6k19 gold badges89 silver badges118 bronze badges
answered Jul 23 at 8:45
kovirolikoviroli
1,2321 gold badge8 silver badges21 bronze badges
1,2321 gold badge8 silver badges21 bronze badges
add a comment
|
add a comment
|
I think it has something to do with how it subtracts value
on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
value
get saved (pushed to the stack) - The
foo()
function returns1
- Now, the
value
is-7
due tofoo()
operation - HERE is the problem: The OLD
value
(which is the one that saved earlier, which is0
) subtracted with1
and the result assigned to the currentvalue
.
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1
, unlike in C.
– Luaan
Jul 25 at 8:04
add a comment
|
I think it has something to do with how it subtracts value
on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
value
get saved (pushed to the stack) - The
foo()
function returns1
- Now, the
value
is-7
due tofoo()
operation - HERE is the problem: The OLD
value
(which is the one that saved earlier, which is0
) subtracted with1
and the result assigned to the currentvalue
.
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1
, unlike in C.
– Luaan
Jul 25 at 8:04
add a comment
|
I think it has something to do with how it subtracts value
on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
value
get saved (pushed to the stack) - The
foo()
function returns1
- Now, the
value
is-7
due tofoo()
operation - HERE is the problem: The OLD
value
(which is the one that saved earlier, which is0
) subtracted with1
and the result assigned to the currentvalue
.
I think it has something to do with how it subtracts value
on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
value
get saved (pushed to the stack) - The
foo()
function returns1
- Now, the
value
is-7
due tofoo()
operation - HERE is the problem: The OLD
value
(which is the one that saved earlier, which is0
) subtracted with1
and the result assigned to the currentvalue
.
edited Jul 25 at 10:46
Peter Mortensen
14.6k19 gold badges89 silver badges118 bronze badges
14.6k19 gold badges89 silver badges118 bronze badges
answered Jul 23 at 9:02
molmol
904 bronze badges
904 bronze badges
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1
, unlike in C.
– Luaan
Jul 25 at 8:04
add a comment
|
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1
, unlike in C.
– Luaan
Jul 25 at 8:04
5
5
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than
-1
, unlike in C.– Luaan
Jul 25 at 8:04
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than
-1
, unlike in C.– Luaan
Jul 25 at 8:04
add a comment
|
value -= foo(); // value = value - foo();
foo()
will return 1
.
value
is initially 0
, so: 0 = 0 - 1
.
Now the value
has -1
.
So the issue is with return 1
.
3
This answer ignores the fact that callingfoo
changesvalue
.
– Theraot
Jul 24 at 10:25
2
@Theraot: This answer is correct; the fact thatfoo
changesvalue
is irrelevant. Regardless of what valuesfoo
changes, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
Jul 25 at 19:14
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
add a comment
|
value -= foo(); // value = value - foo();
foo()
will return 1
.
value
is initially 0
, so: 0 = 0 - 1
.
Now the value
has -1
.
So the issue is with return 1
.
3
This answer ignores the fact that callingfoo
changesvalue
.
– Theraot
Jul 24 at 10:25
2
@Theraot: This answer is correct; the fact thatfoo
changesvalue
is irrelevant. Regardless of what valuesfoo
changes, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
Jul 25 at 19:14
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
add a comment
|
value -= foo(); // value = value - foo();
foo()
will return 1
.
value
is initially 0
, so: 0 = 0 - 1
.
Now the value
has -1
.
So the issue is with return 1
.
value -= foo(); // value = value - foo();
foo()
will return 1
.
value
is initially 0
, so: 0 = 0 - 1
.
Now the value
has -1
.
So the issue is with return 1
.
edited Jul 25 at 10:31
Peter Mortensen
14.6k19 gold badges89 silver badges118 bronze badges
14.6k19 gold badges89 silver badges118 bronze badges
answered Jul 23 at 8:03
Arun Pandian kArun Pandian k
1058 bronze badges
1058 bronze badges
3
This answer ignores the fact that callingfoo
changesvalue
.
– Theraot
Jul 24 at 10:25
2
@Theraot: This answer is correct; the fact thatfoo
changesvalue
is irrelevant. Regardless of what valuesfoo
changes, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
Jul 25 at 19:14
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
add a comment
|
3
This answer ignores the fact that callingfoo
changesvalue
.
– Theraot
Jul 24 at 10:25
2
@Theraot: This answer is correct; the fact thatfoo
changesvalue
is irrelevant. Regardless of what valuesfoo
changes, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
Jul 25 at 19:14
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
3
3
This answer ignores the fact that calling
foo
changes value
.– Theraot
Jul 24 at 10:25
This answer ignores the fact that calling
foo
changes value
.– Theraot
Jul 24 at 10:25
2
2
@Theraot: This answer is correct; the fact that
foo
changes value
is irrelevant. Regardless of what values foo
changes, the fact is that subtraction in C# proceeds from left-to-right.– Eric Lippert
Jul 25 at 19:14
@Theraot: This answer is correct; the fact that
foo
changes value
is irrelevant. Regardless of what values foo
changes, the fact is that subtraction in C# proceeds from left-to-right.– Eric Lippert
Jul 25 at 19:14
1
1
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
Jul 25 at 19:15
1
1
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
@Theraot i have explained only the core-concept, remaining upto you.
– Arun Pandian k
Aug 1 at 11:45
add a comment
|
9
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
Jul 23 at 7:28
52
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
Jul 23 at 7:33
8
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
Jul 23 at 7:36
14
value -= foo()
is the same asvalue = current value of value (0) - foo() which returns 1
, which is the same asvalue = 0 - 1
.foo()
does decrementvalue
but only after you've referenced it in the calculation that callsfoo()
. Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
Jul 23 at 7:43
3
Statements like
i += i++;
are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
Jul 24 at 19:43