Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when creating a variable? [closed]

Tags:

variables

c#

void Method1()
{
string str = 
client.GetString("http://msdn.microsoft.com");

}

What exactly happens when the first line in Method1 is carried out?

I understand memory is set aside for the string variable str, but does the right-hand side of the statement also get carried out at this stage? i.e. does it actually retrieve a value for the right-hand side?

like image 312
jim bob Avatar asked Aug 13 '18 12:08

jim bob


People also ask

What does 5 year variable closed mortgage mean?

The 5-year variable mortgage is Canada's most popular variable-rate mortgage. It is called a variable-rate mortgage because the rate is based on a lender's Prime rate, and can go up or down throughout the 5 years of the mortgage.

What does a closed variable mean?

This mortgage interest rate fluctuates with the prime rate while payments remain the same. If prime goes down, more of your monthly payment is applied to the principle balance of the mortgage. If prime increases, more goes to the interest.

What is the difference between variable open and variable closed?

Variable-rate mortgages can be open or closed. The main differences between closed and open variable-rate mortgages are cost and flexibility. With an open mortgage, you can make additional mortgage payments without the fear of a prepayment penalty, but you pay for this flexibility with a higher interest rate.

What is the difference between open and closed variable mortgages?

An open mortgage is one with flexible options to increase your mortgage repayments, either by increasing your regular payments or via a lump sum. A closed mortgage, on the other hand, will penalize you for paying off all or part of your mortgage early.


1 Answers

This depends a lot on what you do next. There's a very good chance that the compiler will actually remove str completely if you don't use it (unless you use it in the next step, or the things you do between now and then are "net zero" in terms of stack positions). It will still execute the call to client.GetString(...), of course; the question is what does it do with the result? There's various ways the compiler can interpret this:

  • as a local:

stack space for the local is reserved as part of the stackframe entry; after the call to GetString the compiler emits stloc (or a variant)

  • as an ambient stack value

no explicit stack space is reserved for the local; after the GetString() it is simply left where it is for the next operation to consume (for example, this would be perfect if followed by a static call like Console.WriteLine(str);); it might also be cloned (dup) if needed multiple times

  • popped

no explicit stack space is reserved for the local; after the GetString() it is simply dropped (pop)

  • as a field

this would apply for iterator blocks and async methods; very complicated to explain

Ultimately, if you really want to know, you need to look at the real code, then look at the IL - ideally compiled in "release" mode.

You can see examples of some of these in this test code on sharplab.io

or copied here:

void Method1_Popped()
{
    string str = client.GetString("http://msdn.microsoft.com");
}
void Method2_LeftOnStack()
{
    string str = client.GetString("http://msdn.microsoft.com");
    Console.WriteLine(str);
}
void Method3_Local()
{
    string str = client.GetString("http://msdn.microsoft.com");
    for(int i = 0;i < 3 ; i++) DoSomethingElse();
    Console.WriteLine(str);
}

becomes:

.method private hidebysig 
    instance void Method1_Popped () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld class SomeClient Foo::client
    IL_0006: ldstr "http://msdn.microsoft.com"
    IL_000b: callvirt instance string SomeClient::GetString(string)
    IL_0010: pop
    IL_0011: ret
} // end of method Foo::Method1_Popped

.method private hidebysig 
    instance void Method2_LeftOnStack () cil managed 
{
    // Method begins at RVA 0x2063
    // Code size 22 (0x16)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld class SomeClient Foo::client
    IL_0006: ldstr "http://msdn.microsoft.com"
    IL_000b: callvirt instance string SomeClient::GetString(string)
    IL_0010: call void [mscorlib]System.Console::WriteLine(string)
    IL_0015: ret
} // end of method Foo::Method2_LeftOnStack

.method private hidebysig 
    instance void Method3_Local () cil managed 
{
    // Method begins at RVA 0x207c
    // Code size 42 (0x2a)
    .maxstack 2
    .locals init (
        [0] string,
        [1] int32
    )

    IL_0000: ldarg.0
    IL_0001: ldfld class SomeClient Foo::client
    IL_0006: ldstr "http://msdn.microsoft.com"
    IL_000b: callvirt instance string SomeClient::GetString(string)
    IL_0010: stloc.0
    IL_0011: ldc.i4.0
    IL_0012: stloc.1
    // sequence point: hidden
    IL_0013: br.s IL_001f
    // loop start (head: IL_001f)
        IL_0015: ldarg.0
        IL_0016: call instance void Foo::DoSomethingElse()
        IL_001b: ldloc.1
        IL_001c: ldc.i4.1
        IL_001d: add
        IL_001e: stloc.1

        IL_001f: ldloc.1
        IL_0020: ldc.i4.3
        IL_0021: blt.s IL_0015
    // end loop

    IL_0023: ldloc.0
    IL_0024: call void [mscorlib]System.Console::WriteLine(string)
    IL_0029: ret
} // end of method Foo::Method3_Local

or as ASM:

Foo.Method1_Popped()
    L0000: mov ecx, [ecx+0x4]
    L0003: mov edx, [0xe42586c]
    L0009: cmp [ecx], ecx
    L000b: call dword [0x2ef71758]
    L0011: ret

Foo.Method2_LeftOnStack()
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: mov ecx, [ecx+0x4]
    L0006: mov edx, [0xe42586c]
    L000c: cmp [ecx], ecx
    L000e: call dword [0x2ef71758]
    L0014: mov ecx, eax
    L0016: call System.Console.WriteLine(System.String)
    L001b: pop ebp
    L001c: ret

Foo.Method3_Local()
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: mov ecx, [ecx+0x4]
    L0006: mov edx, [0xe42586c]
    L000c: cmp [ecx], ecx
    L000e: call dword [0x2ef71758]
    L0014: mov ecx, eax
    L0016: call System.Console.WriteLine(System.String)
    L001b: pop ebp
    L001c: ret
like image 168
Marc Gravell Avatar answered Oct 29 '22 06:10

Marc Gravell