11

私はCに比較的慣れていないので、プロジェクトの1つに次を使用する必要があります。プログラムが同じメモリアドレスで実行されるたびに格納する必要があるいくつかのグローバル変数を宣言する必要があります。いくつか読んだところ、同じメモリ位置に保存されることを「静的」と宣言していることがわかりました。

しかし、私の質問は、その変数をどこに格納するかをプログラムに示すことができるかどうかです。例:intaは0xff520000に格納されます。これはできるかどうか?ここで検索しましたが、関連する例は見つかりませんでした。彼らがこれに関する古い投稿である場合は、リンクを共有してください。

よろしくお願いします。ローレンティウ

更新:私は32uCを使用しています

4

8 に答える 8

12

IDEには、いくつかのリンカーファイルを介して利用可能なメモリマップがあります。プログラム内のすべてのアドレスが含まれます。MCUのマニュアルを読んで、目的に有効なメモリがどのアドレスにあるかを確認し、そのメモリの一部を変数用に予約します。特定の開発プラットフォームのドキュメントを読む必要があります。

次に、変数がハードウェアレジスタであるか、フラッシュまたはEEPROMに存在する不揮発性変数でない限り、特定のアドレスに変数をマップすることはあまり意味がないことに注意してください。

そのようなメモリ位置の内容が実行中に変更される場合、それがレジスタであるため、またはプログラムにNVMメモリセルを変更するブートローダー/ NVMプログラミングアルゴリズムが含まれている場合、変数は揮発性として宣言する必要があります。そうしないと、コンパイラは最適化時にコードを完全に破壊します。

特定のコンパイラには、#pragmaや、場合によっては奇妙な非標準の@演算子など、特定のアドレスに変数を割り当てる非標準の方法がある可能性があります。標準Cの固定位置に変数を割り当てることができる唯一の賢明な方法は、次のとおりです。

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u)

ここで、0x12345678は、その1バイトが配置されているアドレスです。このようなマクロ宣言を作成したら、それを変数であるかのように使用できます。

void func (void)
{
  MY_REGISTER = 1;  // write
  int var = MY_REGISTER;  // read
}

ほとんどの場合、これらの種類の変数をグローバル名前空間、つまりマクロに配置する必要があります。ただし、何らかの理由で変数のスコープを縮小したい場合は、マクロをスキップして、コード内のアドレスに手動でアクセスしてください。

void func (void)
{
  *(volatile uint8_t*)0x12345678u = 1; // write
  int var = *(volatile uint8_t*)0x12345678u; // read
}
于 2013-03-07T10:32:36.940 に答える
8

この種のことは、組み込みプログラミングで非常に一般的なリンカースクリプトを使用して行うことができます。

Linuxシステムでは、アドレス空間のランダム化(説明したような変数の正確な場所を知ることに依存するエクスプロイトを回避するためのセキュリティ機能)が原因で、同じ仮想アドレスを取得できない場合があります。

繰り返し可能なポインタであれば、特定のアドレスをでマップできる可能性がありますがmmap、それは保証されていません。

于 2013-03-07T09:11:38.553 に答える
2

他の回答で言及されたように-あなたはできません。ただし、回避策を講じることができます。グローバルがで初期化されてmain()も問題がない場合は、次のようなことを行うことができます。

int addr = 0xff520000;

int main()
{
    *((int*)addr) = 42;
    ...
    return 0;
}

ただし、これはシステムに大きく依存し、保護された環境で実行している場合は、ランタイムがクラッシュする可能性が高いことに注意してください。組み込み/保護されていない環境にいる場合、これは機能します。

于 2013-03-07T09:16:44.843 に答える
1

いいえ、変数をメモリのどこに格納するかを明示的に指示することはできません。主に、最近のシステムでは、メモリに関してシステムによって多くのことが行われているため、それは制御できません。アドレス配置のランダム化は、これを非常に困難にすることを思い浮かぶ1つのことです。

于 2013-03-07T09:10:19.313 に答える
1

XC8コンパイラを使用する場合は、コンパイラに応じて。単純にintx@0x12と書くことができます;

この行では、メモリ位置0x12にxを設定します

于 2020-10-07T14:17:11.027 に答える
0

いくつかのコンパイラ拡張機能を使用してこれを行うことができますが、おそらくそれはあなたがやりたいことではありません。オペレーティングシステムはメモリを処理し、必要な場所に配置します。必要なメモリアドレスがプログラムにマップされることをどうやって知ることができますか?組み込みプラットフォームを使用している場合は、この段落のすべてを無視してください。そのプラットフォーム/コンパイラのマニュアルを読むか、少なくともここで言及して、人々がより具体的な回答を提供できるようにする必要があります。

また、静的変数は、プログラムの実行時に必ずしも同じアドレスを持っているとは限りません。多くのオペレーティングシステムは、位置に依存しない実行可能ファイルを使用し、実行ごとにアドレス空間をランダム化します。

于 2013-03-07T09:14:26.587 に答える
0

経営幹部レベルではありません。アセンブリ言語を使用する場合は、メモリレイアウトを直接制御できます。しかし、Cコンパイラがこれを行います。あなたは本当にそれを台無しにすることはできません。

アセンブリを使用する場合でも、これは相対的なレイアウトのみを制御します。仮想メモリは、これを任意の(不)便利な物理的な場所に配置できます。

于 2013-03-07T09:10:46.927 に答える
0

特定のメモリアドレスへのポインタを宣言し、そのポインタの内容を変数として使用できます。

int* myIntPointer = 0xff520000;
于 2013-03-07T09:16:07.187 に答える