Just a Blog

부끄러운 C 코드 분석 본문

IT, Computer

부끄러운 C 코드 분석

wehong 2022. 3. 24. 10:34

얼마 전 다음과 같은 내용을 보게 되었다.

https://twitter.com/lunasorcery/status/1504893095661424644

 

luna 💙 on Twitter

“a lot of people don't know this - C actually lets you do arithmetic with mixed types, much like JavaScript:”

twitter.com

C 언어가 JavaScript 같이 동작하지는 않을 것이기 때문에 문자열 "-0.5"가 숫자(numeric) -0.5로 자동 변환되지 않음은 자명한데, 왜 결과가 0.5가 나오는지가 이해가 되지 않았다. 정말 C 언어를 한참 동안 놓고 있어서 감각을 잃어버린 것인가 싶었다.

 

리눅스에서 코드를 써서 컴파일하고 돌려 봤는데 정말 '0.5'가 출력되었다.

 

아직도 이해가 안되는 상황이라 결국 컴파일된 어셈블리 언어로 확인해 보기로 했다.

gcc -S test.c -masm=intel

 

그랬더니 그제서야 상황이 이해되었다.

        .file   "test.c"
        .intel_syntax noprefix
        .text
        .section        .rodata
.LC0:
        .string "-0.5"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        lea     rax, .LC0[rip+1]
        mov     rdi, rax
        call    puts@PLT
        nop
        pop     rbp
        .cfi_def_cfa 7, 8
                .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
        .section        .note.GNU-stack,"",@progbits

 

결국 해당 계산의 핵심은 이것이었다.

lea     rax, .LC0[rip+1]

즉, 텍스트 스트링 "-0.5"가 있는 어드레스에서 +1 만큼 포인터 연산을 한 것이다. 그러니 'puts()' 함수에 전달되는 인자값은 "-0.5" 문자열 시작 어드레스가 아니라 그 어드레스보다 1만큼 증가한 다음 주소, 즉 '-' 캐릭터 위치 다음인 '0' 캐릭터 위치가 된다. 그리고 'puts()'는 그 주소부터 string terminator가 있는 것 까지 출력할 것이니, '-'가 빠진 '0', '.', '5'를 출력하여 우리가 '0.5'를 보게 되는 것이다. 비슷한 식으로 하면 'puts("-0.5"+3)'의 결과는 '5'이다.

 

코드를 처음 딱 보고 바로 알아차린 사람들도 많을텐데, 바로 이해하지 못한 것이 것이 부끄럽다. 너무 오랫동안 C 언어를 보지 않았나 보다.

 

 

<추가>

그 다음에 있는 코드도 혼란스럽게 보인다. 역시 C 언에에서 문자열 "2"가 자동으로 숫자 2로 캐스팅되지 않으며 '**' 같은 산술연산자도 없다.

역어셈블해보면 그냥 50*50을 계산해서 출력한다. 코드의 데이터 섹션에 "%d\n"은 있지만 "2"는 없고 명령어 오퍼랜드로 50이 두 번 사용된다. 큰 힌트는, 캐릭터 '2'의 ASCII 코드 값이 50이라는 것!

결국, 두 경우 모두 C 언어에서 하나의 중요한 특징을 강조하는 듯 하다. "C 코드에서 문자열 표현 구문은 결국 '주소(address)'다."

Comments