1

これは、 Cでシンボル連結が行われる方法です。

#define conc(a,b) a ## b

例えば:

conc(hello,World)シンボルを作成しますhelloWorld

私が知る必要があるのは少し違います。n整数を保持する変数があるとします。ここで、別のシンボルを の nと連結してシンボルを作成する必要があります。

例えば:

n = 2
私はいくつかfunction(...)を 定義するfunction(symbol,n)必要がsymbol1ありsymbolnます。n = 3function(symbol,n)symbol3

そのようなものをどのように定義できますか?


これが私が本当に達成したいことです。まず、これはマイクロコントローラAtmelStudioをプログラムするために使用されます。atmegaそこには 4 つUSARTのモジュールがあるため、個別のレジスタ セットがあり、モジュールの番号だけで名前が変わります。

たとえば、4 つのモジュールの 4 つのボー レート レジスタはUBRR0L、、、、UBRR1Lです。(さらにいくつかあります。以下を参照してください)。UBRR2LUBRR3L

ここに画像の説明を入力

関連するレジスタの値を設定して、特定のモジュールを初期化する関数を作成する必要があります。レジスタ名はモジュール番号によってのみ異なるため、この投稿で質問されているようにプリプロセッサ ディレクティブを定義できれば、レジスタ名をシンボルで表す単一の関数を記述できるため、シンボルには関連するレジスタ名が付けられ、うまくいくだろう..

例えば:

必要なことを行うように定義できればconc(a,b)、単純な関数

void init(int no){
    conc(UBRR,no) = 0xF0;
}

以下のすべてを表すために使用できます。

UBRR0 = 0xF0;
UBRR1 = 0xF0;
UBRR2 = 0xF0;
UBRR3 = 0xF0;

これが達成できない場合、私が知っている唯一のことは、4 つの別個の関数を書き直すことです。しかし、より良い代替手段があることを願っています..

4

4 に答える 4

5

プリプロセッサは、コンパイルの前に、そして明らかに実行時のかなり前に、コードで動作します。そのため、目的を解決できるプリプロセッサ ディレクティブはありません。

最も近い一致は、次のように switch ケースを使用することです。

switch(n){
case 0: ptr=&symbol0; break;
case 1: ptr=&symbol1; break;
case 2: ptr=&symbol2; break;
case 3: ptr=&symbol3; break;
case 4: ptr=&symbol4; break;
case 5: ptr=&symbol5; break;
//etc... needs to be filled manually.
}

そして次に操作し*ptrます...

また、変数名が連続する場合は、名前をシンボルとして &symbol0に変更した配列を使用してみませんsymbol[0]か?

編集:質問の編集を見ました。上記のように大文字と小文字を切り替えたりUBRR0LUBRR0Lなどを保持するポインターの配列を作成したり、インデックスで使用したりできます。私の知る限り、それらは単なるレジスターであり、固定アドレスに存在します。

于 2013-01-07T12:21:16.650 に答える
4

変数の値は実行時に決定されるため、C プリプロセッサを使用してこれを行うことはできません。ただしsnprintf()、実行時にそのような数値に基づいて文字列を作成するために使用できます。

于 2013-01-07T12:17:31.383 に答える
2

レジスタ (RXC0、RXC1、RXC2 など) が等距離にあるように見えます。この仮定が正しい場合、次のレジスタのアドレスを計算できます (単純にレジスタrintのタイプに置き換えます)。

rint *
register_address(rint *first, rint *second, unsigned int n)
{
    size_t diff = second - first;

    return first + diff * n;
}

関数init()は次のようになります。

void
init(int no)
{
    *register_address(&UBRR0, &UBRR1, no) = 0xF0;
}

この関数呼び出しは、マクロによって単純化/非表示にすることができます。

#define register_value(name, no) *register_address(&conc(name, 0), &conc(name, 1), no)

だからあなたは書くことができます:

void
init(int no)
{
    register_value(UBRR, no) = 0xF0;
}

このコードはテストされておらず、実際に機能するかどうかはわかりません。それが機能し、それを使用する場合は、静的アサートによって仮定をテストします。

于 2013-01-07T21:16:43.703 に答える