昨夜Cで質問されましたが、大学時代からCをあまり使っていなかったので答えがわからなかったので、忘れずにここで答えが見つかるのではないかと思いました。
人が次のような定義を持っている場合:
#define count 1
その人は、その中にある1を使用して変数名を見つけることができますcount
か?
カウントが1を指すと思ったので、そうは思いませんでしたが、1がカウントに戻る方法がわかりません。
昨夜Cで質問されましたが、大学時代からCをあまり使っていなかったので答えがわからなかったので、忘れずにここで答えが見つかるのではないかと思いました。
人が次のような定義を持っている場合:
#define count 1
その人は、その中にある1を使用して変数名を見つけることができますcount
か?
カウントが1を指すと思ったので、そうは思いませんでしたが、1がカウントに戻る方法がわかりません。
@Cade Roux の回答に基づいて、プリプロセッサ #define を使用して値をシンボルに関連付けると、プリプロセッサが実行されるとコードはシンボルを参照しなくなります。
#define COUNT (1)
...
int myVar = COUNT;
...
プリプロセッサの実行後:
...
int myVar = (1);
...
したがって、他の人が指摘したように、これは基本的に「いいえ」を意味します。
簡単な答えは、できないということです。#そのような定義はプリプロセッサによって処理され、一方向のみを指します。もちろん、他の問題は、コンパイラでさえ知らないということです。「1」は何かを指している可能性があるため、複数の変数が同時に同じ値を持つ可能性があります。
その人は、その中にある 1 を使用して、変数名「count」を見つけることができますか?
いいえ
私よりも雄弁で精通している人が #define されたものはソースにコンパイルされていないと指摘するだろうと確信しているので、あなたが持っているのは、ソースを通過して「カウント」のすべてのインスタンスを変更するプリプロセッサマクロです。 ' '1' で検索します。
ただし、あなたが尋ねられた質問にもっと光を当てるために、C はマシン コードに至るまでコンパイルされた言語であるため、Java や C# のような言語で得られるリフレクションやイントロスペクションは決して得られません。ソース/コンパイラを中心に構築されたフレームワークを使用して、気の利いたことを行う場合を除き、コンパイル後にすべての命名が失われます。
これが役立つことを願っています。(しゃれを許して)
残念ながら、これは不可能です。
#define
ステートメントはプリプロセッサの命令であり、のすべてのインスタンスはcount
に置き換えられ1
ます。実行時には、に関連付けられたメモリの場所がないcount
ため、この作業は明らかに無駄です。
変数を使用している場合でも、コンパイル後、プログラムで使用されている元の識別子の残りはありません。これは通常、動的言語でのみ可能です。
C で使用される 1 つのトリックは、マクロで # 構文を使用して、マクロ パラメーターの文字列リテラルを取得することです。
#define displayInt(val) printf("%s: %d\n",#val,val)
#define displayFloat(val) printf("%s: %d\n",#val,val)
#define displayString(val) printf("%s: %s\n",#val,val)
int main(){
int foo=123;
float bar=456.789;
char thud[]="this is a string";
displayInt(foo);
displayFloat(bar);
displayString(thud);
return 0;
}
出力は次のようになります。
foo: 123
bar: 456.789
thud: this is a string
#define count 1
変数や構造フィールドに名前を付けることができないため、非常に悪い考えですcount
。
例えば:
void copyString(char* dst, const char* src, size_t count) {
...
}
マクロcount
によって変数名が に置き換えられ1
、この関数のコンパイルが妨げられます。
void copyString(char* dst, const char* src, size_t 1) {
...
}
C の定義は、変数ではなく、プリプロセッサ ディレクティブです。プリプロセッサは C ファイルを調べて、コンパイルする前に、カウントを記述した場所を定義したものに置き換えます。このディレクティブやその他のプリプロセッサ ディレクティブの特に賢明な使用法については、難読化された C コンテスト エントリを参照してください。
ポイントは、「1」値を指す「カウント」がないことです。コードが実際にコンパイルされる前に行われるのは、単純な置換操作の検索だけです。
C を実際に知っている人が修正できるように、これを編集可能なままにしておきます。
count
変数ではありません。ストレージは割り当てられておらず、シンボル テーブルにもエントリがありません。これは、ソース コードをコンパイラに渡す前にプリプロセッサによって置き換えられるマクロです。
質問が適切でない場合は、マクロを使用して名前を取得する方法があります。
#define SHOW(sym) (printf(#sym " = %d\n", sym))
#define count 1
SHOW(count); // prints "count = 1"
この#
演算子は、マクロ引数を文字列リテラルに変換します。
「#」で始まるディレクティブは、通常、コードを「実際の」コンパイラに渡す前にテキスト置換を行うプリプロセッサによって処理されます。そのため、countという変数はありません。これは、コード内のすべての「count」文字列が魔法のように「1」文字列に置き換えられているかのようです。
だから、いや、その「変数」を見つける方法はありません。
マクロの場合、これは前処理され、結果の出力がコンパイルされます。したがって、プリプロセッサがジョブを終了した後、結果のファイルにはファイル内のすべての場所に「count」ではなく「1」が含まれるため、その名前を見つける方法はまったくありません。
したがって、答えはノーです。
彼らがCソースコード(デバッガーにある)を見ている場合、彼らは次のようなものを見るでしょう
int i = count;
その時点で、彼らは戻って検索し、行を見つけることができます
#define count 1
ただし、それらが持っているのが変数iDontKnowWhatだけであり、それが1を含むことがわかる場合、それを「カウント」まで追跡する方法はありません。
なんで?#defineはプリプロセッサ時に評価されるため、コンパイル前でも発生します(ただし、ほとんどの場合、コンパイルの最初の段階と見なすことができます)。したがって、ソースコードは、それが存在したことを知っているなど、「カウント」に関する情報を持っている唯一のものです。コンパイラーが調べてみるまでに、「count」へのすべての参照は番号「1」に置き換えられています。
これはポインタではなく、単なる文字列/トークンの置換です。プリプロセッサは、コードがコンパイルされる前にすべての#defineを置き換えます。ほとんどのコンパイラには、プリコンパイルされたコードを出力するための-Eまたは同様の引数が含まれているため、すべての#directivesが処理された後のコードがどのようになるかを確認できます。
あなたの質問にもっと直接的に言えば、トークンがコードで置き換えられていることを知る方法はありません。あなたのコードは(count == 1)と(1 == 1)の違いさえわかりません。
本当にそれを実行したい場合は、ソースファイルのテキスト分析を使用して、たとえば差分ツールを使用することが可能かもしれません。
「見つける」とはどういう意味ですか?
この線
#define count 1
値が1のシンボル「カウント」を定義します。
コンパイルプロセスの最初のステップ(前処理と呼ばれる)では、シンボルカウントが発生するたびに1に置き換えられるため、次のようになります。
if (x > count) ...
次のように置き換えられます。
if (x > 1) ...
これを取得すると、「カウントの検索」が無意味である理由がわかる場合があります。
質問者 (インタビューの質問でしたか?) は、#define 定数と列挙型の使用を区別させようとしている可能性があります。例えば:
#define ZERO 0
#define ONE 1
#define TWO 2
対
enum {
ZERO,
ONE,
TWO
};
コードを考えると:
x = TWO;
#defines の代わりに列挙を使用すると、一部のデバッガーは、数値 2 だけでなく、値の記号形式 TWO を表示できます。
#define
プリプロセッサ ディレクティブであるため、「変数」ではありません
そこにあるのは実際には変数ではなく、プリプロセッサ ディレクティブです。コードをコンパイルすると、プリプロセッサが実行され、そのファイル内の単語「count」のすべてのインスタンスが 1 に置き換えられます。
あなたは、count がそれを指している 1 を見つけることができるかどうか、私が知っているかどうか尋ねているかもしれません。いいえ。変数名と値の間の関係は全単射ではないため、元に戻す方法はありません。検討
int count = 1;
int count2 = 1;
完全に合法ですが、何を解決する必要がありますか?
一般的に、いいえ。
まず、#define は変数ではなく、コンパイラのプリプロセッサ マクロです。
コンパイラのメイン フェーズが開始されるまでに、名前は値に置き換えられ、「count」という名前はコンパイルされたコードのどこにも存在しません。
変数の場合、実行時に C コードで変数名を見つけることはできません。その情報は保持されません。Java や C# などの言語とは異なり、C は、アセンブリ言語へのコンパイルで、多くのメタデータをまったく保持しません。