2

いくつかのコードを見つけたので、これを正しく理解していることを確認したいと思います。ユースケースは、値の配列で表されるパックされたイメージです。この例では、3 つの値が 1 つのピクセルを表しています。

私が見つけたコードは次のようになります。

struct Pixel{ 
  int[3] data
  int x(){return data[0];}
  int y(){return data[1];}
  int z(){return data[2];}
};

void main(){

  std::vector<int> img(300);
  Pixel* access = reinterpret_cast<Pixel*>(img.data()+3*5);
  foo(access->x());
}

POD と standard layoutを読んでわかるように、Pixel の最初のメンバーしか使用していないため、コード例は有効だと思いますか? 次に、Pixelを次のように置き換えます

struct Pixel2{
  int red;
  int green;
  int blue;
};

未定義の動作になりますか?

編集:私はcudaを使用して、別の例を見つけました:uchar3ポインターへのキャストおよびunsigned charポインター(配列)。uchar3 型の定義は、2 番目のピクセルの定義と同じです。これは、2番目も有効であることを意味しますか?それとも、これは nvcc によってコンパイルされたコードに対してのみ機能しますか? 2 番目の Pixel 定義が有効である場合、その理由は何ですか?

編集:コードが何をしようとしているのかをさらに強調するために、上記のいくつかのフィールドの名前を変更しました:生データの配列があります。私の場合、それはパックされたイメージです。ピクセルとその値にアクセスするための良い方法が必要です。だから私はこのようなことができます:

void bar(int* data,size_t size)
{
   Pixel2* img = reinterpret_cast<Pixel*>(data);
   std::cout << "Pixel 13 has blue value: " << img[13].blue;
}

cuda でこれを使用しているコードを見たことがありますが、動作しましたが、POD について読んだ内容ではカバーされていないように見えるため、常に問題ないかどうかを知りたいです。POD に関する何かを見逃しただけですか、それとも失敗する可能性があるものですか?

編集:次の違いがあります:

  foo(access->x());
  foo(access->data[0]);

POD 型の場合、最初のメンバー変数がオブジェクトと同じアドレスを持っているため、2 番目は合法であるべきだと思いましたか?

編集:回答から得たものは、私が言及したすべてのケースでUBです。進むべき道は、私が望むアクセスを私に与えるランダムアクセスイテレータです。

4

2 に答える 2