2017-10-11 10 views
-5

コードを直接記述します。メモリを上書きするためにダブルポインタがint変数を指しています

#include <stdio.h> 
struct A 
{ 
    int a; 
    int b; 
}; 
int main() 
{ 
    struct A test; 
    double *p = (double *)&(test.a); 
    *p = 5; 

    printf("variable a: %d\n", &test.a); 
    printf("variable b: %d\n", &test.b); 
    return 0; 
} 

私はcentos7でこのコードを実行すると、コンパイラはgcc4.8.5ある.AND私のコンピュータは、店にはほとんどエンディングを使用しています。ご覧のとおり

、変数bのメモリが上書きされます、私はa0x0000 0005で、b0x0000 0000であると予想しました。

しかし、答えは次のとおりです。

variable a: 0 
variable b: 1075052544 

変数a0x 0000 0000で、b0x4014 0000あるのはなぜ?

+5

これは未定義の動作です:

クランコンパイラは警告メッセージを生成します。また、 'double' 5は64ビット整数' 0x4014000000000000'に対応していますので、何が起きているのか分かります。ヒント: 'double'は' int'より大きくなります。 – unwind

+3

あなたはあなたのコンパイラに嘘をついたので予期せぬ結果を得て、あなたに戻っていく方法を考え出しました。コンパイラに、 '&(test.a)'は 'double'のアドレスですが、整数のアドレスです。 – dasblinkenlight

+0

最適化の設定を変えて、結果が* else *のコードをコンパイルするようにコンパイラを得ることができます。 –

答えて

4

コードの動作はで、定義されていませんです。

doubleタイプではないアドレスに一度設定すると、pを参照解除することはできません。

コンパイラがこの入力で行ったことを確認するには、生成されたアセンブリをチェックします。

+0

私のコンピュータでは、 'int'は4バイトを占め、' double'は8バイトを占有しています。intと代入のdoubleポインタを使用していますので、変数bの値を上書きする必要があります。また、 '1075052544'は、実行または変更の最適化ごとに変化しない固定値です。 – UKeeySDis

+1

あなたは思っているものを考えることができます。それは明らかに起こっていることではありません。事実は未だ定義されていないという事実が残っている。 – Bathsheba

+0

double5は64ビット整数「0x4014000000000000」に対応します。したがって、「b」は「0x4014 0000」、変数bの値は4バイトの残りの半分になります。 – UKeeySDis

1

コードの動作は未定義です。

source_file.c:13:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat] 
    printf("%d\n", &test.a); 
      ~~  ^~~~~~~ 
source_file.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat] 
    printf("%d\n", &test.b); 
      ~~  ^~~~~~~ 
関連する問題