struct FOO{
int a;
int b;
int c;
};
volatile struct FOO foo;
int main(void)
{
foo.a = 10;
foo.b = 10;
foo.c = 10;
struct FOO test = foo;
return 0;
}
struct FOO test = foo;
がエラーを生成するため、これはコンパイルされません。
エラー:タイプ 'const FOO&'から 'volatile FOO'へのバインディング参照は修飾子を破棄します
C++(C++ 11より前)でvolatile struct
を別のstruct
にコピーするにはどうすればよいですか?
多くの人々は揮発性を単に削除することを提案しましたが、現在のSPI-Reg設定をµC内にコピーし、これが製造元のヘッダーによって揮発性であると宣言されているため、私はそれを行うことができません。これらの設定をコピーしたいのは、メーカーがSPI for EnDat-Communicationを使用するためのライブラリも提供しており、ソースコードにアクセスできないためです。変更する必要があるので、ランタイム中のSPI-Reg-Settingsは、再度init_endat()-lib fktを呼び出さなくても簡単にライブラリのSPI-settingsに戻したいです(2回呼び出すと何が起こるかは不定です)。
そのためにmemcopy()を使用できますか?
提案されたように、これは次の質問のコピーです。
FOO
には暗黙のコピーコンストラクターが次のように定義されているため、これは不正な形式です。
FOO(FOO const&);
そして、あなたはFOO test = foo;
with foo
with type volatile FOO
、呼び出し:
FOO(volatile FOO const&);
ただし、参照から揮発性への参照から不揮発性への参照への暗黙的な変換は、形式が正しくありません。
ここから、2つの解が現れます:
const_cast
はvolatile修飾子を削除できますが、これは、基礎となるオブジェクトが実質的に揮発性である場合に使用する未定義の動作です。そのためにmemcopy()を使用できますか?
いいえ、できません。memcpy
はvolatileオブジェクトと互換性がありません。volatileへのポインターを取るオーバーロードはなく、未定義の動作を呼び出さずにできることはありません。
したがって、結論として、FOO
にコンストラクターを追加できない場合の最善の方法は、以下を定義することです。
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}
またはC++ 11の std::tie
:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
std::tie(result.a, result.b, result.c) = std::tie(other.a, other.b, other.c);
return result;
}
答えに別のアプローチを与えるには、C++標準でこれが無効であると述べている場所だけでなく、なぜこれが意味をなさないのかを説明します。
volatile
の要点は、いつどの変数にアクセスするかを正確に制御できることです。つまり、volatile int i, j;
、i = 1; j = 2;
、j = 2; i = 1;
を指定しても、同じことは行われません。コンパイラは、一方を他方に自由に変換することはできません。同じことが読み取りにも当てはまります。指定されたvolatile int i, j; int x, y;
、x = i; y = j;
、およびy = j; x = i;
は同じことを行いません。 volatile
の存在は、アクセスmustがexactlyで発生したことを意味し、指定した順序でアクセスします。
さて、あなたの例では、struct FOO test = foo;
は何をすべきですか?最初にfoo.a
、次にfoo.b
、最後にfoo.c
、または最初にfoo.c
、次にfoo.b
、最後にfoo.a
、またはその他の順序のいずれを読み取るかを指定したことはありません。
あなたが望むなら、これを行うことができます:
struct FOO test;
test.a = foo.a;
test.b = foo.b;
test.c = foo.c;
ここでは、foo
のフィールドへのアクセス順序を明示的に指定して、問題を回避しています。
より正確な評価を行うために問題について十分な詳細を提供していませんが、解決しようとしている問題の解決策は、ほとんどの場合volatile
を使用しないことです。 「揮発性」とは、足元から値が変更される可能性があることを意味します。2つの一般的な優れた使用例は、UNIXシグナルハンドラー内およびメモリマップレジスタ内から変更された変数です。特にスレッド間で共有される変数については、揮発性では不十分です。
このエラーが発生する理由は、コンパイラがFOO(volatile FOO&)
コピーコンストラクタを見つけようとしているためです。これは決して自動的に生成されません。