2

float floatBuffer[4]配列を定義し、構造体を持っているとしましょう。struct vec3{float x,y,z;} myVec;

vec3を割り当てる前に、次を割り当てます。floatBuffer[3] = 0.0f;

(これが可能な場合)どのようmyVecfloatBuffer[0](バイナリコピー)に割り当てることができますか?

  • floatBuffer [0] == myVec.x

  • floatBuffer [1] == myVec.y

  • floatBuffer [2] == myVec.z

  • floatBuffer [3] == 0.0f

4

4 に答える 4

2

標準では、 standard-layout-structの内部 (先頭ではない) にもパディングがある可能性があると述べているため、バイナリ コピーは移植できない可能性があります。ただし、特定のシステムと梱包指示 (ルックアップ#pragma pack) があれば、 を使用できる場合がありますmemcpy

次のことを試すことができます。

#include <cstring>
#include <algorithm>
#include <iterator>
#include <iostream>

// look up your compiler's documentation
//#pragma pack(4) 

struct fs {
 float x, y, z;
};

int main() {
 fs b = {1.0, 2.0, 3.0};
 float p[ 4 ] = {0};
 static_assert( sizeof b == sizeof p - 1, "warning: padding detected!" );
 std::memcpy(&p[ 0 ], &b, sizeof p - 1);
 std::copy(&p[ 0 ], &p[ 0 ] + 3, std::ostream_iterator<float>(std::cout, "\n"));
}
于 2012-05-01T19:12:38.563 に答える
1

memcpyを使用することは可能ですが、前述のように、memcpyはパッキングによっては壊れやすい場合があります。

ここでの最善の解決策は、複数のステートメントを使用することであり、トリッキーにならないことだと思います。

floatBuffer[0] = myVec.x; 
floatBuffer[1] = myVec.y; 
floatBuffer[2] = myVec.z; 

それを明白な方法で行うことによって...コードは何が起こっているのかを明確にし、コンパイラーにコードを最適化させることができます。

頭に浮かぶ質問の1つは、vec3またはvec3配列(単一の割り当てを許可する)ではなく、float配列を使用している理由です。

于 2012-05-01T19:22:09.550 に答える
1

明らかな答えは次のとおりです。

floatBuffer[0] = myVec.x;
floatBuffer[1] = myVec.y;
floatBuffer[2] = myVec.z;

構造体のレイアウトに仮定を置いても構わないと思っていて、コンパイラが直接代入に対してくだらないコードを生成する場合は、仮定を文書化し、次のことを行いますmemcpy

static_assert(sizeof(myVec) == sizeof(float[3]), "myVec should not have padding");

memcpy(&floatBuffer[0], &myVec, sizeof(myVec));
于 2012-05-01T18:55:46.843 に答える
1

このための関数を作成できます。

struct vec3{float x,y,z;} myVec;

float* operator<< (float t[4], vec3 v) {
  t[0] = v.x; t[1] = v.y; t[2] = v.z; t[3] = 0;
  return t;
}

int main() {
  float test[4];
  test << myVec; // now do the assignment 'in one go'
  return 0;
}
于 2012-05-01T19:34:21.143 に答える