두 번째 질문은 0.00
을 파이썬으로 반환하는 방법입니다.
당신이 주장하는 경우 :
import struct
def misinterpret_int_as_double(n):
int_bytes = struct.pack('i', n)
padding = b'\x00' * (struct.calcsize('d') - struct.calcsize('i'))
return struct.unpack('d', int_bytes + padding)[0]
>>> misinterpret_int_as_double(-145)
2.1219957193e-314
이 본질적으로 당신의 C 코드가 무대 뒤에서 무엇을하고 있는지. C는 varargs 함수를 호출 할 때 ...
부분에 전달 된 인수에 대해 컴파일 할 때 (컴파일시 또는 런타임) 형식 검사를 수행하지 않습니다. 무엇 발생하는 printf
의 인수를 저장하는 메모리가 포함되어 있습니다 :
"%.2lf
리터럴 문자열에 대한 포인터.
- 숫자 -145를 나타내는 바이트. (x86-32 또는 x86-64에서는 4 바이트
91 FF FF FF
입니다.)
- 일부 가비지 데이터입니다. (위의 파이썬 코드에서, 이것은 모두 제로로 가정하지만 C 프로그램에서이 일 필요는 없다.)
printf
기능은 lf
지정자를보고하고 double
을 기대하고있다. 따라서 다음 바이트 인 91 FF FF FF xx xx xx xx
(여기서 xx
= 가비지)을 하나로 해석합니다. 쓰레기의 가능한 값의 1/4 (00 00 00 00
포함)의 경우 숫자는 0으로 반올림하기에 충분히 작습니다.
4 바이트의 int
및 8 바이트의 double
을 가진 리틀 엔디안 시스템을 보유하고 있다는 점에 유의하십시오. 함수 인수는 메모리에서 오름차순으로 전달됩니다. 그리고 코드가 segfault하지 않습니다. 다른 하드웨어/OS/컴파일러 조합의 YMMV. 그것이 정의되지 않은 동작을하는 방식입니다.
Python은 안전하게 입력되므로 다른 방식으로 작동합니다. “ 형식이 str
의 %
연산자 인 %
으로 잘못 전달되면 마법 __float__
메서드 (또는 __str__
또는 __int__
또는 어떤 형식인지에 관계없이)를 호출하여 피연산자를 올바른 형식으로 자동 변환합니다.
물론 @ouah는 정확합니다. C는 사용자가 보여준 코드에서 어떤 일이 발생하는지에 대해 아무 것도 정의하지 않습니다. 그것은 플랫폼에 따라 다를 것이고, 횡포를 표시하는 것에서 segfault로 붕괴 될 수 있습니다. C의'printf' 패밀리는이 방법으로 오류를 범하기 쉽다. 두 번째 질문에 대답하기 위해, 당신은 파이썬을 이런 식으로 "트릭"할 수 없습니다. 파이썬이 -145를 정수 이외의 것으로 취급 할 방법이 없습니다. –
이상하지만 괜찮습니다. –