2009-05-28 20 views
4

基本的には、バッファのアドレスにポインタのアドレスを格納したいと思います。なぜ私に尋ねないでください整数をバッファにコピーするmemcpy C++

char * buff = "myBuff"; 
char * myData = (char*)malloc(sizeof(char*)); 
int addressOfArgTwo = (unsigned int)buff; 
memcpy(myData, &addressOfArgTwo, sizeof(char*)); 

cout << "Int Val: " << addressOfArgTwo << endl; 
cout << "Address in buffer:" << (unsigned int)*myData << endl; 

私は上記のコードが動作しない理由がわかりません。これは、出力:

Int Val: 4472832 
Address in buffer:0 

バッファ内のIntヴァル&アドレスが同じであるべきとき。ありがとう

+0

おかげですべての –

答えて

8

char *を逆参照してcharを結果として返し、その4バイトのアドレス全体ではなく、その1バイトのcharをintにキャストします(32ビットマシンの場合は64バイトのマシンで8バイト、ビット)。 4472832は16進数で444000です。リトルエンディアンのマシンでは、最後の00を取得します。

*((unsigned int*)myData) 

正しい番号が表示されます。

1
Instead of (int)*myData, it should be *((int*)myData) 
1

マイケルは、この行が

cout << "Address in buffer:" << *((unsigned int*)myData) << endl 
1

これは、一般的に危険であるべきであると述べたとおり

*((unsigned int*)myData) 

インテルIA-32は、(誰もがするために使用されますことを)アンアラインドアクセスをサポートしていますが、他のいくつかのアーキテクチャはそうしない。変数の整列が必要です(1バイト境界の8ビットデータ、2バイト境界の16ビットデータ、4バイト境界の32ビットデータ)。境界整列を必要とするアーキテクチャでは、境界整列されていないアクセスが破損したデータを返すか、CPU例外をスローします。私はそれが過去の仕事で実生活でのバグを引き起こしているのを見ました。これは、(埋め込みプラットフォーム上で)使用していたソフトウェアパッケージに付属のディスクドライバのためにファイルシステムが破損する微妙なバグです。

myDataのアドレスがmalloc()から来ていることがわかります。これはすべてのタイプのポインタで適切に整列されていることを意味しますが、小さなポインタを大きなポインタにキャストするのは一般的に危険です。ポインタがどこから来たのかわからない。

任意のメモリ位置から32ビット整数を抽出する安全な方法は、生の文字列としてソースメモリを治療、一時的な32ビット整数を宣言し、それにコピーを行うことである。

unsigned int GetUnalignedLittleEndianUInt32(void *address) 
{ 
    unsigned char *uc_address = (unsigned char *)address; 
    return (
     (uc_address[3] << 24) | 
     (uc_address[2] << 16) | 
     (uc_address[1] << 8) | 
     uc_address[0] 
    ); 
} 

またはより一般的には(いくつかの関数呼び出しのオーバーヘッドを含む):

unsigned int GetUnalignedUInt32(void *address) 
{ 
    unsigned int value; 
    memcpy(&value, address, sizeof(value)); 
    return value; 
} 

実際のmemcpyのちょうど逆の(ある)あなたが最初の場所でそこにポインタを取得することでした。

intとしてポインタを処理する、けれども:マイケルが指摘したようにあなたは、32ビットと64ビットのアーキテクチャ間で移動している場合

int addressOfArgTwo = (unsigned int)buff; 

は、また危険です。ポインタは常に32ビットの整数ではありません。後で変更できるtypedefの使用を検討してください。 Linuxでの規約は、ポインターが長いものと同じサイズであることです。 Windowsでは、typedefs INT_PTR、UINT_PTR、LONG_PTR、およびULONG_PTRがあります。だから、

、私は最終的に(とにかくWindows上)を示唆している:あなたの助けを

ULONG_PTR GetAddressAtAddress(void *address) 
{ 
    ULONG_PTR value; 
    memcpy(&value, address, sizeof(value)); 
    return value; 
} 
関連する問題