Are these expressions the same?

5

Good, fiddling with C # and C ++ I've found that the following type of expressions is valid:

int A, B, C, D, E;
A = B = C = D = E = 1;

According to this action, I am assigning 1 in E , E in D and so on, until the end.

My question principal is this, why is this kind of expression valid?

According to the IL ( Generated by DotNetFiddle ) when doing this action, I get this:

.method public hidebysig static void  Main() cil managed
{
// 
    .maxstack  2
    .locals init (int32 V_0,
                  int32 V_1,
                  int32 V_2,
                  int32 V_3,
                  int32 V_4)
    IL_0000:  nop
    IL_0001:  ldc.i4.1
    IL_0002:  dup
    IL_0003:  stloc.s    V_4
    IL_0005:  dup
    IL_0006:  stloc.3
    IL_0007:  dup
    IL_0008:  stloc.2
    IL_0009:  dup
    IL_000a:  stloc.1
    IL_000b:  stloc.0
    IL_000c:  ret
} // end of method Program::Main

And the IL generated by the following assignment:

A = 0; B = 0; C = 0; D = 0; E = 0;

It is the following:

.method public hidebysig static void  Main() cil managed
{
// 
    .maxstack  1
    .locals init (int32 V_0,
                  int32 V_1,
                  int32 V_2,
                  int32 V_3,
                  int32 V_4)
    IL_0000:  nop
    IL_0001:  ldc.i4.0
    IL_0002:  stloc.0
    IL_0003:  ldc.i4.0
    IL_0004:  stloc.1
    IL_0005:  ldc.i4.0
    IL_0006:  stloc.2
    IL_0007:  ldc.i4.0
    IL_0008:  stloc.3
    IL_0009:  ldc.i4.0
    IL_000a:  stloc.s    V_4
    IL_000c:  ret
} 

I do not understand much about IL but according to the previous code, the method that assigns a variable in another, occupies more space in memory and so, or something similar (Please correct me if I'm wrong) .

My question is, do both codes really do the same thing?

    
asked by NaCl 02.06.2016 в 22:12
source

2 answers

5

Below the explanation of the IL of the first case

.method public hidebysig static void  Main() cil managed
{
// 
    .maxstack  2                  // Denota que la pila tendrá máximo 2 elementos
    .locals init (int32 V_0,      // Declara las 5 variables de tipo Int32
                  int32 V_1,
                  int32 V_2,
                  int32 V_3,
                  int32 V_4)
    IL_0000:  nop                 // Autogenerado cuando se compila como DEBUG
    IL_0001:  ldc.i4.1            // Se coloca en la pila el valor 1
    IL_0002:  dup                 // Se duplica el valor 1 en la pila como segundo elemento
    IL_0003:  stloc.s    V_4      // Se desapila el segundo 1 y se almacena en la variable V_4 (E)
    IL_0005:  dup                 // Se duplica de nuevo el valor 1
    IL_0006:  stloc.3             // Se desapila el tercer 1 y se almacena en la variable 3 (V_3/D)
    IL_0007:  dup                 // Se duplica en valor 1 en la pila
    IL_0008:  stloc.2             // Se desapila el cuarto 1 y se almacena en la variable 2 (V_2/C)
    IL_0009:  dup                 // Se duplica el valor 1 en la pila
    IL_000a:  stloc.1             // Se desapila el quinto 1 y se amancena en la variable 1 (V_1/B)
    IL_000b:  stloc.0             // Se desapila el primer 1 y se apila en la variable 0 (V_0/A)
    IL_000c:  ret
} // end of method Program::Main

In this case the algorithm that follows is to place the value 1 in the stack and then duplicate that value to store it temporarily so that it can continue to be assigned after assigning it to the corresponding variable, first to% co_of% then to V_5 and so on until there is no need to temporarily store the variable, at the end the stack remains empty and the value V_4 assigned to all the variables

In the second case assuming that the expression was: 1

.method public hidebysig static void  Main() cil managed
{
// 
    .maxstack  1                  // Se define el tamaño máximo de pila en 1
    .locals init (int32 V_0,      // Se declaran las 5 variables de tipo Int32
                  int32 V_1,
                  int32 V_2,
                  int32 V_3,
                  int32 V_4)
    IL_0000:  nop                // Generado al compilar como DEBUG
    IL_0001:  ldc.i4.1           // Se apila el valor 1
    IL_0002:  stloc.0            // Se desapila el 1 y se asigna a la variable 0 (V_0/A)
    IL_0003:  ldc.i4.1           // Se apila el valor 1
    IL_0004:  stloc.1            // Se desapila el 1 y se asigna a la variable 1 (V_1/B)
    IL_0005:  ldc.i4.1           // Se apila el valor 1
    IL_0006:  stloc.2            // Se desapila el 1 y se asigna a la variable 2 (V_2/C)
    IL_0007:  ldc.i4.1           // Se apila el valor 1
    IL_0008:  stloc.3            // Se desapila el 1 y se asigna a la variable 3 (V_3/D)
    IL_0009:  ldc.i4.1           // Se apila el valor 1
    IL_000a:  stloc.s    V_4     // Se desapila el 1 y se asigna a V_4 (E)
    IL_000c:  ret
}

In this case, the simplest algorithm consists of stacking the value 1 and assigning it to the corresponding varible. This is repeated 5 times.

As we can see in this case in the stack, there is only one element at a time, since it is stacked and unstacked immediately, in the previous case there were up to two A = 1; B = 1; C = 1; D = 1; E = 1; since the same value was doubled each instead of stacking the same value 5 times.

Now answering because the first syntax in C # is valid, it is due to the following

The 1 has a return value and is the same value that is assigned to the variable on the left side, that is:

A = B = C = D = E = 1;

equals

A = (B = (C = (D = (E = 1))));

and executing it step by step:

A = (B = (C = (D = (E = 1))));    // E == 1
...
A = (B = (C = (D = 1)));          // E == 1, D == 1
...
A = (B = (C = 1));                // E == 1, D == 1, C == 1
...
A = (B = 1);                      // E == 1, D == 1, C == 1, B == 1
...
A = 1;                            // E == 1, D == 1, C == 1, B == 1, A == 1
    
answered by 02.06.2016 / 23:17
source
2
int A, B, C, D, E;
A = B = C = D = E = 1;
  

My main question is this, why this kind of   Expressions is valid?

The second statement contains multiple assignment expressions , an assignment expression assigns a value to a variable:

A = 1;

But that value can be an assignment expression by itself:

A = B = 1;

First, the allocation expression B = 1 is evaluated, which results in 1 and that value is assigned to A . The same process is repeated for all variables in the chain of assignments.

This is found in the specification of language 7.13.1

  

The result of a simple assignment is the value assigned to   the left operand. The result has the same type as the left operand and   is always classified as a value.

At the IL level the code is different, however the result is the same when assigning the same value to all the variables.

A = 1; B = 1; C = 1; D = 1; E = 1;
    
answered by 02.06.2016 в 23:03