2학년인데 강제 형변환쪽을 수업하다 실습시간에 내 후배가 물어봐서 코드를 봤는데 아래처럼 나옴.
#include <stdio.h>
int main()
{
int a=8;
int b=0;
double c = 2.5;
b = a*c;
printf("%d, %lf, %d", c, c, b); //4byte 8byte 4bye
}
출력이
0, 0.000000, 1074003968 가 나와서 이상하다고 했음.
--- 이하 내가 분석해본 내용
처음에 컴파일러 문제인가 해서 컴파일러 여러개 써봤는데 똑같이 나왔음.(visual, intel, mingw, clang, c++ builder, 리눅스 gcc)
출력은
0, 0.000000, 1074003968 (x86)
0, 2.500000, 20 (x64)
다른 방법으로
1074003968를 변환해봄
10진수: 1074003968 => 10자리
16진수: 40040000 => 8자리
2진수: 1000000000001000000000000000000 => 31자리
8진수: 10001000000 => 11자리
20을 int형으로
0000 0000 0000 0000 0000 0000 0001 0100(2)
0000 0014(HEX)
2.5를 float이랑 double형으로
2.5 -> float
01000000001000000000000000000000
1075838976(10)
40200000(16)
2.5 -> double
0100000000000100000000000000000000000000000000000000000000000000(2)
4612811918334230528(10)
4004000000000000(16)
여기서 내가 생각한것이 확실히 1074003968이 2.5를 double형으로 변환한거랑 관계가 있는거 같았음.
메모리에 들어가는게
%d, %lf, %d(double, double, int)라서
2.5, 2.5 20의 오리지널 DATA
4004 0000 0000 0000, 4004 0000 0000 0000, 0000 0014
32bit READ
4004(안읽음) 0000(읽음, 0출력) 0000 0000(읽음, 0.000000출력) 4004 0000(읽음, 1074003968출력) 0000 0000 0000 0014
64bit READ
4004 0000(안읽음) 0000 0000(읽음, 0출력) 4004 0000 0000 0000(읽음, 2.500000출력) 0000 0014(읽음, 20출력)
인거 같은데 맞나 모르겠네.. 컴퓨터는 진짜 알다가도 모르겠어 T.T
" 말고 '써서 그런건 아니고?
"
모바일이라 그런가 다 작은따옴표로 보이는데 여튼
모바일은 이상하게 나오나요??
ㄴㄴ내가 문제였음 모바일로 보니까 다 작은따옴표인데 피시로 보니까 큰ㅌ다옴표네
...본격 아키텍쳐에따른 프로그램 열화론(...)
double형 변수를 %d로 출력할때의 문젠데 예전에 배운건데 생각이 안나네
이게 printf의 취약점중 하나였는데 별로 중요한내용이 아니라 까먹었다
암튼 첫번쨰 %d에 해당하는 c를 c말고 (int)c 하면 제대로나온다. 이거 double형을 %d로 출력할떄 내부에서 이상하게동작해서그래
찾아보니 포맷 스트링쪽을 한번 봐보면 되겠네요. 이거 설명하는 것도 머리아프겠다...
이거 64bit에서는 레지스터에서 각각 들어가서 문제가 안생기고
32bit는 램을 이용해서 호출하기때문에 문제가 생긴건데
더블이 왜 저값이 떴냐면 0(부호)| |10000000000(지수부 - bias)| | 0100000000000000000000000000000000000000000000000000요러케해서 1.01에다가 2곱한건데
네. 그건 알고 있습다.
그럼 명령 처리양 때문에 64bit은 레지스터에서 처리가 되는 건가요?
printf가 어케도는지는 모르겠는데 32비트면 포맷스트링 기준으로 파라미터 위치를 계산하나봄
아녀 64비트는 범용레지스터 많아서 abi수준에서 걍 레지스터 사용해서 호출하도록 정의돼있음
저거 엔디안 뒤집어서 넣은다음에 오프셋은 앞에두는게 맞을듯
그럼 딱 맞네여
아항 감사합니다.
이것도 막 레지스터 모자랄때까지 파라미터 넣으면 64비트에서도 이상해질것같은게 저도 궁금함
처음에 간단한 줄 알았는데 생각보다 어렵군여 ㅠㅠ
근데 왜 이게 캐스팅 배우는데서 나왔는지 의문임
아키텍쳐 알아야되는건데 ㅋㅋ
제가 동아리에서 1학년 얘들한테 C 가르치는데 하다가 물어봐서....
이래서 printf scanf가 병신소리 듣는거지. 알고리즘 할때 아니면 쓰지도 않음
그.. 그렇군요;;;