簡単なテストコードがあるとしましょう
typedef struct
{
int first;
int second;
int third;
} type_t;
#define ADDRESS 0x12345678
#define REGISTER ((type_t*)ADDRESS)
const int data = (int)(®ISTER->second)*2;
int main(void)
{
volatile int data_copy;
data_copy = data;
while(1) {};
}
これは、ベアメタルARM用にCodeSourcery G ++(gcc 4.3.2)でコンパイルされています。また、非常に標準的なリンカースクリプトもあります。
Cで(main.cとして)コンパイルすると、オブジェクト「データ」は期待どおりにFlashに入ります。C ++で(main.cppとして)コンパイルされると、このオブジェクトはRAMに入れられ、フラッシュからRAMに値をコピーするだけの追加コードが追加されます(値はすでに計算されています。コピーするだけです!)。したがって、コンパイラはアドレスを計算できますが、どういうわけか「それを使用する」ことを望んでいません。問題の根本は、アドレスの乗算です。「* 2」の乗算がないと、両方のバージョンが期待どおりに機能します。「データ」はFlashに配置されます。また、「データ」が次のように宣言されている場合:
const int data = (int)(REGISTER)*2;
また、すべてが大丈夫です。
CおよびC++コンパイルのすべてのファイルは同一であり、唯一の違いはコンパイラーの呼び出しです。main.cppの場合はg ++、main.cの場合はgccです(警告のレベルに違いがあり、c ++ではRTTIと例外が無効になっています)。
この「C++の問題」を克服するための簡単でエレガントな方法はありますか?Cortex-M3のビットバンド領域のビットのアドレスのconst配列を作成するには、このような操作が必要です。これはバグですか、それともC ++コンパイラの奇妙な制限ですか?
「C」ファイルでデータオブジェクトを作成し、「extern」だけでデータオブジェクトを作成できることは知っています。C++にそれらを含めますが、それはあまりエレガントではありません[;
助けてくれてありがとう!