CSAPP第二章show_bytes函數的探究

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語言基礎的應該都能看懂,所以在看懂函數後,我第一時間想自己實現一下,實現代碼如下:

#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類型的數字

int main(void)
{
    int x=1;
    show_int(x);
}

VS2017運行結果爲:
TIM截圖20191119161542.png
看上去是沒什麼問題的。於是我又試了一下浮點數的表示:

int main(void)
{
    float x = 1.0f;
    show_float(x);
}

VS2017運行結果爲:
TIM截圖20191119162023.png
輸出了14個十六進制數字,多輸出了6個十六進制數,即3個字節。
這三個字節是怎麼來的呢?
通過對比發現我寫的函數與書中的函數一個不同,書中的byte_pointerunsigned char*,而我的是char*
這有什麼問題呢,charunsigned char都是一個字節,八位二進制,兩位十六進制,爲什麼會發生多輸出三個字節的情況呢。
通過查閱,我發現問題正出在charunsigned char中:c語言中 char* 和 unsigned char* 的區別淺析
具體原因是這樣的:
C語言中雖然沒有具體說明char有無符號,但是大多數機器上char都是有符號的,而printf中格式輸出%.2x的過程爲:先把char類型轉換爲int類型,然後再把int類型轉換爲二進制。這就涉及到了位的擴展,而有符號數的位擴展所遵循的是--‘符號擴展’具體見我的新博客~。
所以在擴展時,如果char類型的位模式中第一位是1的話,擴展爲int類型,需要在前面加三個字節24位的1,printf時實際精度超過了.2x,自然就在這個字節的前面加了六個f。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章