3
int i=512;
char *c = (char *)&i;
c[0] =1;
printf("%d",i);

これは「513」と表示され、i に 1 が加算されます。

int i=512;
char *c = (char *)&i;
c[1] =1;
printf("%d",i);

これは 256 を表示します。これを 2 で割ります。誰か理由を説明してもらえますか? どうもありがとう

4

6 に答える 6

12

バイナリ

バイナリで表現された 32 ビット数 512 は、次のとおりです。

00000000000000000000001000000000

2 の 9 乗は 512 であるためです。通常、ビットは右から左に読み取られます。

2進数の他の10進数は次のとおりです。

0001 = 1
0010 = 2
0011 = 3
0100 = 4

キャスト: Int をバイト配列として再解釈する

これを行う場合:

int i = 512;
char *c = (char *)&i;

おそらくご存知のように、4 バイト整数を文字の配列 (8 ビット バイト) として解釈しています。そうでない場合は、次のようになります。

&i

変数のアドレスを取得しますi

(char *)&i

char 型へのポインターに再解釈 (またはキャスト) します。これは、配列のように使用できるようになったことを意味します。intはマシン上で少なくとも 32 ビットであることがわかっているため、 を使用してそのバイトにアクセスできますc[0], c[1], c[2], c[3]

システムのエンディアンに応じて、数値のバイトが配置される場合があります。最上位バイトが最初 (ビッグ エンディアン) または最下位バイトが最初 (リトル エンディアン) です。x86プロセッサはリトル エンディアンです。これは基本的に、数字 512 が上記の例のように配置されていることを意味します。

00000000 00000000 00000010 00000000
    c[3]     c[2]     c[1]     c[0]

ビットを、メモリ内でのレイアウト方法に対応する個別の 8 ビット チャンク (バイト) にグループ化しました。ここでも右から左に読むことに注意してください。これにより、2 進数システムの規則を守ることができます。

結果

現在、設定c[0] = 1には次の効果があります。

00000000 00000000 00000010 00000001
    c[3]     c[2]     c[1]     c[0]

これは2^9 + 2^0 == 51310進数です。

設定c[1] = 1には次の効果があります。

00000000 00000000 00000001 00000000
    c[3]     c[2]     c[1]     c[0]

2 番目のバイト 00000010 を 00000001 で上書きしたため、これは2^8 == 25610 進数です。

ビッグ エンディアンシステムでは、バイトはリトルエンディアンシステムとは逆の順序で格納されることに注意してください。これは、これらのマシンで実行した場合とはまったく異なる結果が得られることを意味します。

于 2012-11-14T19:19:28.623 に答える
2

char は 8 ビットであり、512 はビット表現であることに注意してください。
512 = 10 0000 0000

あなたchar *c = (char *)&i;が作るとき:

c[1] = 10
c[0] = 0000 0000

c[0] = 1 を実行すると10 0000 0001、513 になります。

c[1] = 1 とすると、01 0000 0000256 になります。

于 2012-11-14T19:16:22.187 に答える
2

表示されているものが「奇妙」である理由を考える前に、コードを実行しているプラ​​ットフォームとそのエンディアンを考慮してください。

次に、次のことを検討してください

int main(int argc, char *argv[])
{
    int i=512;
    printf("%d : ", i);
    unsigned char *p = (unsigned char*)&i;
    for (size_t j=0;j<sizeof(i);j++)
        printf("%02X", p[j]);
    printf("\n");

    char *c = (char *)&i;
    c[0] =1;
    printf("%d : ", i);
    for (size_t j=0;j<sizeof(i);j++)
        printf("%02X", p[j]);
    printf("\n");

    i = 512;
    c[1] =1;
    printf("%d : ", i);
    for (size_t j=0;j<sizeof(i);j++)
        printf("%02X", p[j]);
    printf("\n");
    return 0;
}

私のプラットフォーム (Macbook Air、OS X 10.8、Intel x64 Arch)

512 : 00020000
513 : 01020000
256 : 00010000

上記の内容とエンディアンについて読んだ内容を組み合わせると、私のプラットフォームがリトル エンディアンであることがはっきりとわかります。それで、あなたのものは何ですか?

于 2012-11-14T19:21:32.783 に答える
1

ポインタintを介してan をエイリアシングしており、aは 8 ビット幅 (1 バイト) であるため、割り当ては次のようになります。charchar

c[1] = 1;

の 2 番目のバイトを に設定i000000001ます。バイト 1、3、および 4 ( の場合sizeof(int) == 4) は変更されません。以前は、その 2 番目のバイトは000000010(リトルエンディアン アーキテクチャである x86 ベースのコンピューターを使用していると想定しているため) だったので、基本的には、設定された唯一のビットを 1 つ右にシフトしました。2で割ったものです。

リトル エンディアンのマシンと 32 ビットのコンパイラではint、最初に次の 4 バイトが にありましたi

  c[0]      c[1]      c[2]     c[3]
00000000  00000010  00000000 00000000

割り当て後、次のiように設定されました。

  c[0]      c[1]      c[2]     c[3]
00000000  00000001  00000000 00000000

したがって、512 から 256 になりました。

これで、513 という結果になる理由が理解できるはずですc[0] = 1:-) どのバイトが 1 に設定され、割り当てによって他のバイトがまったく変更されないかを考えてみてください。

于 2012-11-14T19:18:22.620 に答える
0

これは、マシンがリトルエンディアンであるためです。つまり、最下位バイトが最初にメモリに格納されます。

あなたは言っint i=512;た。5120x0000020016 進数です (簡単にするために 32 ビット OS を想定しています)。i16 進数のバイトとしてメモリに格納される方法を見てみましょう。

  00 02 00 00  // 4 bytes, least-significant byte first

次に、同じメモリ位置を文字配列として解釈しますchar *c = (char *)&i;-同じメモリ、異なる解釈:

  00 02 00 00
c[0][1][2][3]

で変更c[0]するc[0] =1;と、メモリは次のようになります

  01 02 00 00

つまり、リトルエンディアンとしてint( を実行して) もう一度見ると、10 進数であるprintf("%d",i);hexです。0x00000201513

戻って で変更c[1]するとc[1] =1;、記憶は次のようになります。

  00 01 00 00

ここで戻って、これをリトルエンディアンとして解釈します。これはinthex0x00000100で、これは25610 進数です。

于 2012-11-14T19:26:08.830 に答える
0

little endianそれがそうであるか、データがビットでどのように格納されているかは、マシンによって異なります。詳細については、エンディアンbig endianについてこれを読んでください

C 言語はこれを保証しません。

512 in binary :

    =============================================
    0000 0000 | 0000 0000 | 0000 0010 | 0000 0000   ==>512
    =============================================
      12          34          56          78       

(0x12345678 この int のアドレスを想定)

char *c =(char *)&i now c[0] either point to 0x78 or 0x12
Modifying the value using c[0] may result to 513 if it points to 0x78
    =============================================
    0000 0000 | 0000 0000 | 0000 0010 | 0000 0001   ==> 513
    =============================================

or, can be 

    =============================================
    0000 0001 | 0000 0000 | 0000 0010 | 0000 0000  ==>2^24+512
    =============================================

同様に 256 の場合も : c 1は右から 2 バイト目のアドレスを持つためです。下の図で、

    =============================================
    0000 0000 | 0000 0000 | 0000 0001 | 0000 0000  ==>256
    =============================================

したがって、私たちのシステムでの数値表現の実装

于 2012-11-14T19:12:35.653 に答える