私は変数からデータをダンプするツールを開発しています。 変数名と値をダンプする必要があります。Cで変数名を取得するためのプログラム的な方法?
解決方法:変数名を文字列として格納し、 "変数名"とそれに続く値を出力します。
変数名を知るプログラム的な方法はありますか?
私は変数からデータをダンプするツールを開発しています。 変数名と値をダンプする必要があります。Cで変数名を取得するためのプログラム的な方法?
解決方法:変数名を文字列として格納し、 "変数名"とそれに続く値を出力します。
変数名を知るプログラム的な方法はありますか?
あなたはこのような何かを試みることができる:私は、私はCに新しいだったとき、それはいくつかの有用なアイデアが含まれているかもしれませんが、私が書いたthis headerを使用するために使用される
#define DUMP(varname) fprintf(stderr, "%s = %x", #varname, varname);
を。たとえば、これを使用すると、C値を印刷し、1で書式指定子(だけでなく、いくつかの付加的な情報)を提供することが可能になります。
#define TRACE(fmt, var) \
(error_at_line(0, 0, __FILE__, __LINE__, "%s : " fmt, #var, var))
あなたがC++を使用している場合は、渡された値のタイプを使用することができますそれを適切に出力する。このような場合に変数値を "きれいに印刷"する方法については、より有益な例を提供することができます。
実行ファイルがデバッグ情報でコンパイルされている場合は、この情報を取得できます。もしそうでなければ、あなたはおそらく運が悪いでしょう。つまり、デバッガをビルドしていますか?どうして?既存のC用デバッガは非常に成熟しています。なぜホイールを再発明するのではなく、既存のツールを使用するのですか?
いくつかの例? –
Cでは、変数名はコンパイルステップ中(変数がグローバル変数の場合はリンクステップ)に存在しますが、実行時には使用できません。変数名を表すリテラル文字列を含むソリューションを選択する必要があります。
あなたのプログラムの中からそれを行うには良い方法はありません。(Anacrolixの答えは別として)恐れています。私はあなたの問題に適切な解決策は、デバッガのスクリプトだと思う。ほとんどのデバッガでは、デバッガがプログラムの実行を中断する(ブレークポイント、^C
などにぶつかる)たびにプログラムの状態をスナップショットとして取得し、それを操作するたびに実行することができます。
任意の変数に対してこれを行う必要がある場合は、おそらく、コンパイラまたはプラットフォームが提供するデバッガAPI(WindowsではDbgHelpなど)を使用する必要があります。
私はいくつかの組み込みシステムで、事前に知られている特定の重要な変数の値をコマンドで表示できるようにする必要がありました。そのために必要なのは単純な名前/ポインタテーブルです:
typedef
struct vartab {
char const* name;
int * var;
} vartab;
vartab varTable[] = {
{ "foo", &foo },
{ "bar", &bar }
};
は、その後、私はちょうど問題の変数名用のテーブルを検索し、名前をダンプ少しルーチンを使用してデータをポインタで指さ。プレーンint以外のデータをダンプする必要がある場合は、構造体を拡張してprintf形式のフォーマッタを保持し、ポインタを
void*
に変更し、そのジャンクを
snprintf()
またはデータの書式設定に渡します。
時々、テーブルを構築するのに役立つマクロを使用します(変数を宣言することもできます)。しかし、正直言って、それは本当に理解するのがより複雑になると思う(特に、プロジェクトに参加する新しい人 - 彼らはしばしば小さな「WTF?」の瞬間を持つ)、事実をあまり単純化しない。
私は実際にあなたが望むことができるいくつかのコードを持っています。これはプリプロセッサを使用して変数名を文字列化し、それを印刷できるようにします。変数名と値(型に基づく)とその変数のメモリレイアウトの両方をダンプします。次のプログラムはどのように行うのを示しています。
#include <stdio.h>
#include <stdlib.h>
static void dumpMem (unsigned char *p, unsigned int s) {
int i;
unsigned char c[0x10];
printf (">> ");
for (i = 0; i < 0x10; i++) printf (" +%x",i);
printf (" +");
for (i = 0; i < 0x10; i++) printf ("%x",i);
printf ("\n");
for (i = 0; i < ((s + 15) & 0xfff0); i++) {
if ((i % 0x10) == 0) {
if (i != 0) printf (" %*.*s\n", 0x10, 0x10, c);
printf (">> %04x ",i);
}
if (i < s) {
printf (" %02x", p[i]);
c[i & 0xf] = ((p[i] < 0x20) || (p[i] > 0x7e)) ? '.' : p[i];
} else {
printf (" ");
c[i & 0xf] = ' ';
}
}
printf (" %*.*s\n", 0x10, 0x10, c);
}
#define DUMPINT(x) do{printf("%s: %d\n",#x,x);dumpMem((char*)(&x),sizeof(int));}while(0)
#define DUMPSTR(x) do{printf("%s: %s\n",#x,x);dumpMem(x,strlen(x));}while(0)
#define DUMPMEM(x,s) do{printf("%s:\n",#x);dumpMem((char*)(&x),s);}while(0)
typedef struct {
char c;
int i;
char c2[6];
} tStruct;
int main (void) {
int i = 42;
char *s = "Hello there, my name is Pax!";
tStruct z;
z.c = 'a'; z.i = 42; strcpy (z.c2,"Hello");
DUMPINT (i);
DUMPSTR (s);
DUMPMEM (z,sizeof(z));
return 0;
}
この出力:
i: 42
>> +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +fabcdef
>> 0000 2a 00 00 00 *...
s: Hello there, my name is Pax!
>> +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +fabcdef
>> 0000 48 65 6c 6c 6f 20 74 68 65 72 65 2c 20 6d 79 20 Hello there, my
>> 0010 6e 61 6d 65 20 69 73 20 50 61 78 21 name is Pax!
z:
>> +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +fabcdef
>> 0000 61 b6 16 61 2a 00 00 00 48 65 6c 6c 6f 00 0d 61 a..a*...Hello..a
そして、あなたはマクロでdo {...} while (0)
の健全性に疑問を抱いているなら、それはどこにでも配置されることを可能にするためですあなたがそれを取り囲む十分な括弧を持っているかどうか心配する必要はありません。
多くの人は、プログラムが自己内観(または現在の専門用語では「反映」)したいと思うことがよくあります。しかし、ほとんどのプログラミング言語は、プログラムのすべての詳細(変数名、関数名、型式、式構造など)を反映する能力はほとんどない(たとえばJava)か、まったくない(C)能力しか提供していません。ステップ外言語、および言語からその情報を抽出するために設計されたツールを使用します。
がありすべての言語のためにこれを行う方法です。これを行うことができるツールのクラスは、プログラム変換システムと呼ばれます。
が、これはSOプログラム変換システムを使用して、プリント値「変数名を取得」する方法の説明については、お答えください: Trace changes to variables automatically
はこれを試してみてください。
#define MACRO_VARIABLE_TO_STRING(Variable) ((void) Variable,#Variable)
コード(void)変数は無効な変換であり、コンマ演算子とマクロstringifyがあります。したがって、結果はconst char *変数名を含んでおり、コンパイラチェックは変数が実際に存在します。
変数の名前があり、printf()を使ってその値を表示できます。
短い方法:
#define GET_VARIABLE_NAME(Variable) (#Variable)
テスト:実行時にデバッガをしてください問い合わせる
#include <string>
class MyClass {};
int main(int argc, char* argv[]) {
int foo = 0;
std::string var_name1 = GET_VARIABLE_NAME(foo);
char* var_name2 = GET_VARIABLE_NAME(foo);
char* var_name3 = GET_VARIABLE_NAME(MyClass);
return 0;
}
それはプログラムの中から何かをするのが良い考えです。文字列定数の束を作成しますが、それは確かです。 –
'fprintf'で' DUMP(varname、format) 'と' "%s =" format "\ n" 'として定義する方が良いでしょう。' DUMP(somestring、 "%s") 'または' DUMP(someint、 "%d") 'となります。 – caf
これは、cの非内省性を取り巻く通常の方法です。あなたが想像しているように、それは限界とトラップを持っていますが、それはあなた自身のイントロスペクティブなインタプリタを構築しなくてもできるほど良いものです。 – dmckee