2013-11-02 54 views
3

我有一小段代碼嘗試演示各種標準整數 類型,並顯示內存似乎首先被分配到堆棧中,並且最大的數據類型爲 。我寫的東西似乎是合理的,直到最後一行,我得到的輸出字節太多了。我真的只想(並期望)只能得到一個字節。一次從一個字節獲取變量存儲器地址的數據

這樣:

#include <stdint.h> /* defines the standard integer types */ 
#include <stdio.h> /* defines all the IO functions */ 
#include <stddef.h> /* standard definitions */ 
#include <stdlib.h> /* standard library functions */ 

int main (int argc, char *argv[]) { 

    int8_t little_i = 11; 
    int16_t med_i = 12062; 
    int32_t norm_i = 1991; 
    int64_t big_i = -3245321806; 

    /* these next items are pointers */ 
    int8_t *little_p; 

    printf ("here is a little 8-bit int : little_i = %02x\n", little_i); 
    printf ("here is a medium 16-bit int : med_i = %04x\n", med_i); 
    printf ("here is a normal 32-bit int : norm_i = %08x\n", norm_i); 
    printf ("here is a big 64-bit int : big_i = %016lx\n", big_i); 

    printf ("addr of little_i is %p" , &little_i); 
    printf (" and the size is %d\n" , sizeof(little_i)); 
    printf ("addr of med_i is %p" , &med_i); 
    printf (" and the size is %d\n" , sizeof(med_i)); 
    printf ("addr of norm_i is %p" , &norm_i); 
    printf (" and the size is %d\n" , sizeof(norm_i)); 
    printf ("addr of big_i is %p" , &big_i); 
    printf (" and the size is %d\n" , sizeof(big_i)); 

    /* tell us about the pointer */ 
    printf ("\n--------------------------------------------------\n"); 
    printf (" size of the pointer little_p is %d\n" , sizeof(little_p)); 
    printf (" the address of the pointer itself is %p\n", &little_p); 

    little_p = &little_i; 

    printf ("\nthe pointer little_p now contains the addr %p\n", little_p); 
    printf ("The data there, in memory, at the addr %p is 0x%02xh\n", 
         little_p, *little_p); 

    /* we can point a pointer anywhere we want */ 
    little_p = (void *) &big_i; 

    printf ("\n\nthe pointer little_p now has the addr %p\n", little_p); 

    printf ("The data there, in memory, at the addr is 0x%02xh\n", 
                *((int8_t*) little_p)); 

    return (EXIT_SUCCESS); 
} 

我得到的輸出看起來不錯,直到最後一行:

$ ./dtypes 
here is a little 8-bit int : little_i = 0b 
here is a medium 16-bit int : med_i = 2f1e 
here is a normal 32-bit int : norm_i = 000007c7 
here is a big 64-bit int : big_i = ffffffff3e9051b2 
addr of little_i is ffffffff7ffff56b and the size is 1 
addr of med_i is ffffffff7ffff568 and the size is 2 
addr of norm_i is ffffffff7ffff564 and the size is 4 
addr of big_i is ffffffff7ffff558 and the size is 8 

-------------------------------------------------- 
size of the pointer little_p is 8 
the address of the pointer itself is ffffffff7ffff550 

the pointer little_p now contains the addr ffffffff7ffff56b 
The data there, in memory, at the addr ffffffff7ffff56b is 0x0bh 


the pointer little_p now has the addr ffffffff7ffff558 
The data there, in memory, at the addr is 0xffffffffh 

我期望看到的最後一行只是一個字節0xffh卻得到了一個完整的32位整數大小的結果。我認爲將little_p強制轉換爲int8_t *類型的指針會起到訣竅的作用。

我錯過了一些明顯的東西嗎?

-----更新就在我張貼了這個問題:

我改變的最後一行有一個投給uint8_t *:

printf ("The data there, in memory, at the addr is 0x%02xh\n", 
               *((uint8_t*) little_p)); 

這使我的輸出:

The data there, in memory, at the addr is 0xffh 

主要是因爲內存中的字節一次無符號8位。

似乎合理。

-----------進一步編輯提取和從64位整數打印字節------

下面是一個更新的代碼塊:

$ cat dtypes.c 
#include <stdint.h> /* defines the standard integer types */ 
#include <stdio.h> /* defines all the IO functions */ 
#include <stddef.h> /* standard definitions */ 
#include <stdlib.h> /* standard library functions */ 

int main (int argc, char *argv[]) { 

    int8_t little_i = 11; 
    int16_t med_i = 12062; 
    int32_t norm_i = 1991; 
    int64_t big_i = -3245321806; 

    void *little_p; /* void datatype is no datatype at all really. */ 

    printf ("here is a little 8-bit int : little_i = %02x\n", little_i); 
    printf ("here is a medium 16-bit int : med_i = %04x\n", med_i); 
    printf ("here is a normal 32-bit int : norm_i = %08x\n", norm_i); 
    printf ("here is a big 64-bit int : big_i = %016lx\n", big_i); 

    printf ("addr of little_i is %p" , &little_i); 
    printf (" and the size is %d\n" , sizeof(little_i)); 
    printf ("addr of med_i is %p" , &med_i); 
    printf (" and the size is %d\n" , sizeof(med_i)); 
    printf ("addr of norm_i is %p" , &norm_i); 
    printf (" and the size is %d\n" , sizeof(norm_i)); 
    printf ("addr of big_i is %p" , &big_i); 
    printf (" and the size is %d\n" , sizeof(big_i)); 

    /* tell us about the pointer */ 
    printf ("\n--------------------------------------------------\n"); 
    printf (" size of the pointer little_p is %d\n" , sizeof(little_p)); 
    printf (" the address of the pointer itself is %p\n", &little_p); 

    /* we can point a pointer anywhere we want */ 
    little_p = (void *) &big_i; 

    printf ("\n\nthe pointer little_p now has the addr %p\n", little_p); 

    printf ("The data there, in memory, at the addr is 0x%02xh\n", 
               *((uint8_t*) little_p)); 

    printf ("        at addr+1 is 0x%02xh\n", 
               *((uint8_t*) little_p+1)); 

    printf ("        at addr+2 is 0x%02xh\n", 
               *((uint8_t*) little_p+2)); 

    printf ("        at addr+3 is 0x%02xh\n", 
               *((uint8_t*) little_p+3)); 

    printf ("        at addr+4 is 0x%02xh\n", 
               *((uint8_t*) little_p+4)); 

    printf ("        at addr+5 is 0x%02xh\n", 
               *((uint8_t*) little_p+5)); 

    printf ("        at addr+6 is 0x%02xh\n", 
               *((uint8_t*) little_p+6)); 

    printf ("        at addr+7 is 0x%02xh\n", 
               *((uint8_t*) little_p+7)); 

    return (EXIT_SUCCESS); 
} 

這給了非常好的結果:

$ ./dtypes 
here is a little 8-bit int : little_i = 0b 
here is a medium 16-bit int : med_i = 2f1e 
here is a normal 32-bit int : norm_i = 000007c7 
here is a big 64-bit int : big_i = ffffffff3e9051b2 
addr of little_i is ffffffff7ffff56b and the size is 1 
addr of med_i is ffffffff7ffff568 and the size is 2 
addr of norm_i is ffffffff7ffff564 and the size is 4 
addr of big_i is ffffffff7ffff558 and the size is 8 

-------------------------------------------------- 
size of the pointer little_p is 8 
the address of the pointer itself is ffffffff7ffff550 


the pointer little_p now has the addr ffffffff7ffff558 
The data there, in memory, at the addr is 0xffh 
          at addr+1 is 0xffh 
          at addr+2 is 0xffh 
          at addr+3 is 0xffh 
          at addr+4 is 0x3eh 
          at addr+5 is 0x90h 
          at addr+6 is 0x51h 
          at addr+7 is 0xb2h 

一切似乎好這裏。

回答

2

這是因爲地址上的數據是0xff,所以它在符號位中有1。這意味着數據在轉換爲int時會進行符號擴展,這會在值傳遞到printf時發生。符號擴展意味着用原始值的符號位填充int的缺失字節。在這種情況下,這意味着用其餘的位填充1,產生一串F s(demo 1)。

將格式更改爲%hhx將解決問題(demo 2;謝謝,Martin R!)。

+0

我剛剛發現我自己。必須記得在早上製作第一杯咖啡,然後在我發佈前思考..但這對我來說可能是合理的教訓。內存不是簽名數據。它只是記憶。 –

+0

也... ..愛你的用戶名。是的,我記得當我們有大的電腦控制室和大量的das blinken燈:-) –

+0

@paullanken:還要注意,用十六進制打印字符大小數量的格式是'%hhx',而不是'%xh'。無論簽名如何,更改格式也會產生預期輸出。 –

1

嘗試轉換爲(uint8_t *),您的字節的值爲0xff,它是十進制的-1,它將符號擴展爲32位,因此它最終爲0xffffffffh(在二進制補碼錶示中再次爲-1)。因此,使用無符號數據的無符號類型。

相關問題