3

さまざまな標準整数型を示し、メモリが最初に最大のデータ型でスタックに割り当てられるように見えることを示す小さなコードがあります。私が書いたものは、出力のバイト数が多すぎる最後の行までは妥当に思えます。私は本当に1バイトだけを取得したかった(そして期待した)だけでした。

したがって :

#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

その最後の行に 1 バイトの 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

ここではすべてが順調に見えます。

4

2 に答える 2

2

これは、アドレスのデータが であるため0xff1符号ビットに含まれています。intこれは、値が に渡されるときに行われる への変換時に、データが符号拡張されることを意味しprintfます。符号拡張とは、 の欠けているバイトをint元の値の符号ビットで埋めることを意味します。この場合、これは残りのビットを 1 で埋めることを意味し、Fs の文字列を生成します ( demo 1 )。

形式を に変更する%hhxと問題が解決します ( demo 2 ; ありがとう、Martin R !)。

于 2013-11-02T13:59:28.283 に答える
1

(uint8_t*) にキャストしてみてください。バイトの値は 0xff で、10 進数では -1 で、32 ビットに符号拡張されるため、最終的に 0xffffffffh (2 の補数表記では -1) になります。そのため、符号なしデータには符号なし型を使用してください。

于 2013-11-02T13:58:35.183 に答える