2

ポインタ演算やメモリの割り当て方法を理解するのに苦労しています。以下のコード スニペットでは、「test」の 8 バイト前にある「size = 1」の値にアクセスしようとしていますが、size の値を取得できず、値はランダムではありません。したがって、バイトサイズの理解に問題がある可能性があります。void*、long、および char が 8 バイトの場合、ポインター演算を使用するときに問題になりますか?

#include <iostream>
using namespace std;

char arrayOfCrap[100];

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[29]);
}

int main(){

    long * test;
    test =  (long*)what();
    *test = 1221;
    cout << "Value of test: " << *test << endl;
    cout << "Long number before test: " << *(test-1) << endl;
}

このコードは、main が what() の void* ' ポインターから前方に移動したときに機能します。

#include <iostream>
using namespace std;

char arrayOfCrap[100];

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[28]);  //change from above
}

int main(){

    long * test;
    test =  (long*)what();
    test++;                             //change from above
    *test = 1221;
    cout << "Value of test: " << *test << endl;
    cout << "Long number before test: " << *(test-1) << endl;
}
4

2 に答える 2

4

あなたのコードは の*size前に 8 バイトを見つけていません*test:

size = (long*)&arrayOfCrap[28];

arrayOfCrap はchar arrayOfCrap[100]arrayOfCrap[28]オフセット 28arrayOfCrap[29]の char とオフセット 29 の char です。

機能する理由test++は、 test が typelong*であるため、実際にインクリメントすると long の次の位置に移動しますが、 a をインクリメントするchar*か、 char 配列でインデックスを使用すると、 char の次の位置が得られます

次のいずれかを行うこともできます。

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return size+1;
}

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[28 + sizeof(long)];
}

ところで、任意のメモリ位置へのポインターを取得して、それを別の型へのポインターとして扱うことは必ずしも安全ではありません。一部のプラットフォームでは、一部の型を「整列」するか、特定の値の倍数であるアドレスにのみそれらの型を存在させる必要があります。これらのプラットフォームでは、アラインされていないオブジェクトの読み取りまたは書き込みがクラッシュ (バス エラー) するか、未定義の動作をする可能性があります。また、一部のプラットフォームはクラッシュしたり正しく動作しない場合がありますが、アライメントされたオブジェクトの読み取り/書き込み時のパフォーマンスが大幅に向上します。これは実験の要点から完全に外れていることはわかっていますが、実際のコードについて知っておくべきことです。実際のコードで行ってはいけないことの例を次に示します。

int read_int(char *&c) {
  int out = *(int*)c; // c may not be properly aligned!
  c += sizeof(int);

  return out;
}

残念ながら、一般的なプラットフォームである x86 では、アラインされていないアクセスは通常、常にクラッシュを引き起こすものではなく単に遅いため、そのプラットフォームのユーザーは特に注意する必要があります。

于 2012-06-21T16:36:33.260 に答える
2

ポインターをインクリメントすると、ポインターのサイズではなく、ポインターの型のサイズだけインクリメントされます。char*ポインタは だけ増加し、ポインタは だけ増加しsizeof(char)ますlong*sizeof(long)

sizeof(char *)sizeof(long *)両方とも同じサイズにする必要があります (通常、32 ビット システムでは 4 バイト、64 ビット システムでは 8 バイト)。

ただし、sizeof(char)sizeof(long)は同じではありません。

ポインタのサイズと整数のサイズを混同しています。

#include <iostream>
using namespace std;

int main()
{
    cout << "\n sizeof(char*)   " << sizeof(char *);
    cout << "\n sizeof(char)    " << sizeof(char);
    cout << "\n sizeof(long*)   " << sizeof(long *);
    cout << "\n sizeof(long)    " << sizeof(long);
}

ここで動作を確認してください: http://ideone.com/gBcjS

于 2012-06-21T16:38:29.167 に答える