# C語言解釋 - 單精確度跟雙精確度 ###### tags: `c`, `single precision`, `double precision` ```clike= #include <stdio.h> #include <stdlib.h> int main() { double a, b; scanf("%f %f", &a, &b); printf("a: %f", a); printf("b: %f", b); } ``` 開編譯器選項,會對格式不對提出警告,不過還是會產生執行檔。 ```clike= src/test_main.c:6:18: warning: format specifies type 'float *' but the argument has type 'double *' [-Wformat] scanf("%f %f", &a, &b); ~~ ^~ %lf src/test_main.c:6:22: warning: format specifies type 'float *' but the argument has type 'double *' [-Wformat] scanf("%f %f", &a, &b); ~~ ^~ %lf src/test_main.c:10:17: warning: more '%' conversions than data arguments [-Wformat-insufficient-args] printf("a+b: %f, a+b"); ``` 一樣用lldb觀察a, b ```clike= (lldb) r Process 1208 launched: '/Users/ewnlm/Work/Clang/KenHW/bin/test_main' (arm64) 1.54 1.581 Process 1208 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100003f34 test_main`main at test_main.c:8:19 5 double a, b; 6 scanf("%f %f", &a, &b); 7 -> 8 printf("a: %f", a); 9 printf("b: %f", b); 10 printf("a+b: %f, a+b"); 11 Target 0: (test_main) stopped. (lldb) frame variable a b (double) a = 2.650588257955044E-314 (double) b = 2.6507581834348151E-314 (lldb) frame variable &a &b (double *) &a = 0x000000016fdfeab8 (double *) &b = 0x000000016fdfeab0 (lldb) x/8 0x000000016fdfeab0 0x16fdfeab0: 0x3fca5e35 0x00000001 0x3fc51eb8 0x00000001 0x16fdfeac0: 0x6fdfec10 0x00000001 0x0001108c 0x00000001 (lldb) po a 2.650588257955044E-314 ``` 輸入1.54, 1.581 兩個值,看第17,18行,實際存進去變成$2.65*10^{-314}$ 一個非常小的值。 ```clike= (lldb) r Process 1281 launched: '/Users/ewnlm/Work/Clang/KenHW/bin/test_main' (arm64) 1.54 1.581 Process 1281 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100003f20 test_main`main at test_main.c:8:20 5 double a, b; 6 scanf("%lf %lf", &a, &b); 7 -> 8 printf("a: %lf", a); 9 printf("b: %lf", b); 10 printf("a+b: %lf", a+b); 11 Target 0: (test_main) stopped. (lldb) frame variable a b (double) a = 1.54 (double) b = 1.581 (lldb) frame variable &a &b (double *) &a = 0x000000016fdfeab8 (double *) &b = 0x000000016fdfeab0 (lldb) x/8 0x000000016fdfeab0 0x16fdfeab0: 0xa7ef9db2 0x3ff94bc6 0x0a3d70a4 0x3ff8a3d7 0x16fdfeac0: 0x6fdfec10 0x00000001 0x0001108c 0x00000001 ``` 把scanf()要掃瞄的格式換成正確的`%lf`. 再看一下a, b 變數的內容; 第17,18行,這次就是正確1.54與1.581. 就這是為什麼會看到 0 的原因。