6

私はCでこのプログラムを持っています:

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

  int i=300;
  char *ptr = &i;
  *++ptr=2;
  printf("%d",i);
  return 0;
}

リトルエンディアンの出力は556です。

出力を理解しようとしました。これが私の説明です。

質問は、答えはビッグエンディアンマシンでも同じままですか?

i = 300; => i =100101100//ワード形式のバイナリ=>BBHb 0001 00101100ここで、B =バイト、Hb=ハーフバイト

(A)=>メモリ内(リトルエンディアンであると想定))

0x12345678 - 1100 - 0010 ( Is this correct for little endian)

0x12345679 - 0001 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

0x1234567c-次の整数の位置(ptr++またはptr+ 1の位置。ptrはint=>型であるため、ptrは整数ポインターです。++ ptrを実行すると、4バイトずつ増加します(intのサイズ))

いつ

(B)char * ptr =&i;を実行します ptrはchar=>型になります。++ptrを実行すると1バイト(charのサイズ)ずつインクリメントされるため、++ ptrを実行すると、場所-> 0x12345679(0001〜0000)にジャンプします 。 + ptr = 2=>0x12345679は2で上書きされます=>0x12345679は000* 1 * -0000ではなく00*10**-0000になります

したがって、新しいメモリコンテンツは次のようになります。

(C)

0x12345678 - 1100 - 0010

0x12345679 - 0010 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

これは、=> BB Hb 0010 00101100と同等です。ここで、B =バイト、Hb=ハーフバイトです。

私の推論は正しいですか?これのための他の短い方法はありますか?Rgds、Softy

4

4 に答える 4

8

リトルエンディアンの32ビットシステムでは、int 3000x012c)は通常(*)4つの連続したバイトとして格納され、最初に最小になります 2C 01 00 00。以前はintポインターであったcharポインターをインクリメントすると&i、そのシーケンスの2番目のバイトをポイントし、2に設定すると、シーケンスが作成されます。2C 02 00 00これは、intに戻すと、0x22cまたは556になります。

(ビットシーケンスの理解については...少しずれているようです。バイトはアドレス可能な最小単位であるため、エンディアンはメモリ内のバイト順序に影響します。バイト内のビットは反転しません。下位バイトシステムがリトルエンディアンであるかビッグエンディアンであるかは2C( )になります(00101100システムがバイトのビットを反転した場合でも、それらを再度反転して数値として表示するため、気付かないでしょう違い。)大きな違いは、そのバイトがシーケンスのどこに現れるかです。ビットの順序が重要なのは、ハードウェアとドライバーなど、一度に1バイト未満しか受信できない場所だけです。)

ビッグエンディアンシステムでは、intは通常(*)バイトシーケンスで表されます00 00 01 2C(リトルエンディアン表現とはバイト順でのみ異なります。上位バイトが最初になります)。ただし、シーケンスの2番目のバイトを変更していますが00 02 01 2C、これはintとして0x02012cまたは131372になります。

(*)ここでは、2の補数(最近ではほとんどすべてのシステムで使用されていますが、Cでは必要ありません)、値sizeof(int)、アライメント/パディング、システムが本当に大きいかどうかなど、さまざまなことが関係しています。またはそれのリトルエンディアンまたは中途半端な実装。これは、より大きなタイプのバイトをいじくり回すと、未定義または実装固有の動作が頻繁に発生する理由の大きな部分です。

于 2012-06-06T06:50:42.103 に答える
3

これはあなたintです:

int i = 300;     

そして、これはメモリに含まれるもの&iです。次の命令でのアドレスをに2c 01 00 00 割り当て、次に次のバイトに移動してその値を:に変更します。iptr++ptr2

char *ptr = &i;
*++ptr = 2;

したがって、メモリには次のものが含まれます:(2c 02 00 00つまり、556)。違いは、あなたのアドレスのビッグエンディアンシステムでは、変更後、次のように表示されることです。i00 00 01 2C00 02 01 2C

の内部表現int実装定義である場合でも:

符号付き整数型の場合、オブジェクト表現のビットは、値ビット、パディングビット、および符号ビットの3つのグループに分割されます。パディングビットは必要ありません。符号付き文字にはパディングビットを含めないでください。正確に1つの符号ビットが必要です。値ビットである各ビットは、対応する符号なしタイプのオブジェクト表現の同じビットと同じ値を持つ必要があります(符号付きタイプにM個の値ビットがあり、符号なしタイプにNがある場合、M≤N)。符号ビットがゼロの場合、結果の値に影響を与えることはありません。符号ビットが1の場合、値は次のいずれかの方法で変更されます。—符号ビット0の対応する値は否定されます(符号と大きさ)。—符号ビットの値は-(2M)(2の補数)です。—符号ビットの値は-(2M − 1)(1の補数)です。実装定義は、符号ビット1とすべての値ビットがゼロ(最初の2つ)、または符号ビットとすべての値ビット1(1の補数)の値がトラップ表現であるか、通常の値であるかを示します。符号と大きさ、および1の補数の場合、この表現が通常の値である場合、それは負のゼロと呼ばれます。

于 2012-06-06T06:46:27.973 に答える
3

これは実装定義です。intの内部表現は標準では不明であるため、実行していることは移植性がありません。C規格のセクション6.2.6.2を参照してください。

ただし、ほとんどの実装では符号付きintの2の補数表現が使用されるため、cHaosの回答で説明されているように、エンディアンが結果に影響します。

于 2012-06-06T06:56:32.850 に答える
1

私は実験が好きで、それがPowerPCG5を持っている理由です。

stacktest.c:

int main(int argc, char *argv[])
{
  int i=300;
  char *ptr = &i;
  *++ptr=2;
  /* Added the Hex dump */
  printf("%d or %x\n",i, i);
  return 0;
}

ビルドコマンド:

powerpc-apple-darwin9-gcc-4.2.1 -o stacktest stacktest.c

出力:

131372 or 2012c

履歴書:cHaoの答えは完全です。疑問がある場合は、ここに実験的な証拠があります。

于 2012-06-06T19:25:10.160 に答える