printf
함수는 전달 된 형식의 형식을 알지 못합니다. 그 부분은 가변적이기 때문입니다. float
지나가는 C 표준에서
int printf(const char* format, ...);
// ^^^
는 자동
double
(C11§6.5.2.2/6)로 승급되고, 아무것도 호출자 측에서 수행되지 않는다.
printf
내부에는 ...
거지 (§6.7.6.3/9)의 유형을 알지 못하므로 형식 문자열 인 다른 곳에서 힌트를 사용해야합니다. "%d"
을 전달 했으므로 int
이 필요하다고 함수에 알립니다.
C 표준에 따르면, 이것은 이상한 숫자, 이야기의 끝을 인쇄 할 가능성을 포함하는 정의되지 않은 동작 (§7.21.6.1/8-9)을 초래합니다.
하지만 실제로 무엇이 일어나고 있습니까? 대부분의 플랫폼에서 double
은 "IEEE 754 binary64"형식으로 표시되고 float
은 binary32 형식으로 표시됩니다. 당신이 입력 한 숫자는 숫자는 다음과 같이 근사 할 것입니다 의미만을 의미의 23 비트가있는 부동 소수점, 변환됩니다 :
이제
3.3 ~ (0b1.10100110011001100110011) × 2¹ (actually: 3.2999999523162842...)
3.4 ~ (0b1.10110011001100110011010) × 2¹ (actually: 3.4000000953674316...)
3.5 = (0b1.11 ) × 2¹ (actually: 3.5)
3.6 ~ (0b1.11001100110011001100110) × 2¹ (actually: 3.5999999046325684...)
4 = (0b1 ) × 2² (actually: 4)
5 = (0b1.01 ) × 2² (actually: 5)
우리는 이것이 의미의 53 비트를 가지고있는 두 배로 변환 , 우리는이 숫자의 끝에 30 개의 이진 "0"을 삽입해야합니다. 나는이가 ± m × 2 전자로 분해 방식을 볼 수 http://www.binaryconvert.com/convert_double.html를 사용하는 것이 좋습니다
3.3 → 400A6666 60000000
3.4 → 400B3333 40000000
3.5 → 400C0000 00000000
3.6 → 400CCCCC C0000000
4 → 40100000 00000000
5 → 40140000 00000000
:
3.299999952316284 = 0b1.10100110011001100110011000000000000000000000000000000 ×2¹
는 이들은 그 숫자의 실제 표현을 유도하기 위해 주로 형식 어쨌든
, 당신의 시스템이 little-endian format를 사용하여 메모리에 배치되어있는 번호를 의미 일반 설정에서의 x86/x86_64의/ARM, 가정하자, 이렇게 전달 된 인수는 될 것 같은 printf
내부
byte
#0 #1 ... #4 ... #8 ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 08 | 10 | 02 | 00 | | 00 | 00 | 00 | 60 | 66 | 66 | 0A | 40 | ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
address of "%d" content of 3.299999952316284
(just an example)
, 그것을 파싱 형식 문자열 "%d"
을 소비하고 그리고, int
가 SO 4 바이트가 가변 입력에서 촬영되고 있기 때문에 % D의 필요하다는 것을 알게되는 :에서 printf
byte
#0 #1 ... #4 ... #8 ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
: 08 : 10 : 02 : 00 : | 00 | 00 | 00 | 60 | 66 : 66 : 0A : 40 : ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
address of "%d" ~~~~~~~~~~~~~~~~~~~
this, as an 'int'
그래서 0x60000000을 받고 10 진수 정수로 표시합니다 (1610612736). 그 결과를 볼 수 있습니다. 다른 숫자도 비슷하게 설명 할 수 있습니다.
3.3 → ... 60000000 = 1610612736
3.4 → ... 40000000 = 1073741824
3.5 → ... 00000000 = 0
3.6 → ... C0000000 = -1073741824 (note 2's complement)
4 → ... 00000000 = 0
5 → ... 00000000 = 0
+1이 모든 것을 쓸 시간입니다. :) – Mysticial
완벽을 기하기 위해 [Two 's Complement - Wikipedia] (http://en.wikipedia.org/wiki/Two%27s_complement)와 [Two 's Complement notes Thomas Finley] (http : // tfinley.net/notes/cps104/twoscomp.html). – mctylr