C# - IL 코드 분석을 위한 팁
다음과 같은 질문이 있군요. ^^
++ 후위연산자와 = 을 함께 사용할 때 생성되는 IL 코드 관련...
; https://www.sysnet.pe.kr/3/0/4796
그러니까 다음의 코드를 컴파일했는데,
void Main()
{
int testValue = 0;
testValue = testValue ++;
Console.WriteLine(testValue);
}
생성된 IL 코드가 이런 식이었다는 것입니다. (nop은 제거했습니다.)
IL_0001: ldc.i4.0
IL_0002: stloc.0 // testValue
IL_0003: ldloc.0 // testValue
IL_0004: stloc.1
IL_0005: ldloc.1
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: stloc.0 // testValue
IL_0009: ldloc.1
IL_000A: stloc.0 // testValue
IL_000B: ldloc.0 // testValue
IL_000C: call System.Console.WriteLine
IL_0012: ret
근데... 사실 IL 출력이 이상하다기보다는 입력부터가 이상하다고 생각해야 합니다. 즉, 아래의 코드가 이상해도 ... 너무 이상한 것입니다. ^^
testValue = testValue ++;
testValue가 후위 연산자라서 값을 증가시켜야 하는데, 증가시킨 값을 무색하게 결국 0으로 돌려야 하는 것입니다. 위의 IL 코드를 2개의 코드로 나누면 결국 다음과 같습니다.
testValue = testValue + 1;
testValue = 0;
또는, testValue + 1의 변수를 다음과 같이 임시 변수로 쓸 수도 있습니다.
testValue = temp + 1;
testValue = 0;
"testValue = testValue ++" 코드를 저렇게 해석하는 것에 이견이 없을 거라고 봅니다. ^^
그렇다면, 출력된 IL 코드가 정말 이상한지 다시 한번 볼까요? IL 코드를 그대로 번역해 보면 다음과 같은 C# 코드로 변환이 가능합니다.
int testValue; // 0번 로컬 변수
int temp; // 1번 로컬 변수
// ldc.i4.0
// stloc.0
testValue = 0;
// ldloc.0
// stloc.1
temp = testValue;
// ldloc.1
// ldc.i4.1
// add
// stloc.0
testValue = temp + 1;
// ldloc.1
// stloc.0
testValue = temp;
// ldloc.0
// call System.Console.WriteLine
Console.WriteLine(testValue);
어떠세요? 이젠 IL 코드가 그다지 비정상적이지 않다고 생각되시죠? ^^
그건 그렇고, IL 코드를 분석할 때의 팁이라고 하면... Debug 빌드의 산출물보다는 Release 빌드의 산출물이 더 다루기 편하다는 점입니다. 아무래도 최적화가 되어 불필요한 것들이 빠지게 되고, 실제로 현업에서 실행될 응용 프로그램의 빌드 버전이기 때문에 더 중요하기도 합니다.
질문자가 제시한 코드를 Release 빌드로 해보면 다음과 같은 코드가 나옵니다.
L_0000: ldc.i4.0
L_0001: call void [mscorlib]System.Console::WriteLine(int32)
L_0006: ret
결국, "testValue = testValue ++"는 "testValue = 0"과 별반 다를 바가 없는 코드인 것입니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]