CSAPP第二章中給出了一個幫助咱們觀察數據的位模式的函數--show_bytes函數,具體實現以下:函數
#include<stdio.h> typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i < len; i++) { printf("%.2x", start[i]); } printf("\n"); } void show_int(int x) { show_bytes((byte_pointer)&x, sizeof(int)); } void show_double(double x) { show_bytes((byte_pointer)&x, sizeof(double)); } void show_float(float x) { show_bytes((byte_pointer)&x, sizeof(float)); }
函數是不難懂的,只要有C語言基礎的應該都能看懂,因此在看懂函數後,我第一時間想本身實現一下,實現代碼以下:.net
#include<stdio.h> typedef char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { for (int i = 0; i < len; i++) { printf("%.2x", start[i]); } printf("\n"); } void show_int(int x) { show_bytes((byte_pointer)&x, sizeof(int)); } void show_double(double x) { show_bytes((byte_pointer)&x, sizeof(double)); } void show_float(float x) { show_bytes((byte_pointer)&x, sizeof(float)); }
寫完後我馬上嘗試跑了一下一個int類型的數字code
int main(void) { int x=1; show_int(x); }
VS2017運行結果爲:
看上去是沒什麼問題的。因而我又試了一下浮點數的表示:blog
int main(void) { float x = 1.0f; show_float(x); }
VS2017運行結果爲:
輸出了14個十六進制數字,多輸出了6個十六進制數,即3個字節。
這三個字節是怎麼來的呢?
經過對比發現我寫的函數與書中的函數一個不一樣,書中的byte_pointer
是unsigned char*
,而個人是char*
。
這有什麼問題呢,char
與unsigned char
都是一個字節,八位二進制,兩位十六進制,爲何會發生多輸出三個字節的狀況呢。
經過查閱,我發現問題正出在char
與unsigned char
中:c語言中 char* 和 unsigned char* 的區別淺析。
具體緣由是這樣的:
C語言中雖然沒有具體說明char有無符號,可是大多數機器上char都是有符號的,而printf中格式輸出%.2x的過程爲:先把char類型轉換爲int類型,而後再把int類型轉換爲二進制。這就涉及到了位的擴展,而有符號數的位擴展所遵循的是--‘符號擴展’具體見個人新博客~。
因此在擴展時,若是char類型的位模式中第一位是1的話,擴展爲int類型,須要在前面加三個字節24位的1,printf時實際精度超過了.2x,天然就在這個字節的前面加了六個f。get