函数调用中的字符串变量名,C ++

时间:2015-08-12 15:14:39

标签: c++

我正在扩展我们的内部调试库,而且我遇到了一个奇怪的问题。我想将变量名称输出为字符串。从本网站的elsewhere开始,我发现可以在文件中使用宏来执行此操作:

@Test
public void testParcel() {
    Comment test = new Comment();
    test.setId(testNr0Id);
    test.setComment(testNr0String);


    // Obtain a Parcel object and write the parcelable object to it:
    Parcel parcel = Parcel.obtain();
    test.writeToParcel(parcel, 0);

    // After you're done with writing, you need to reset the parcel for reading:
    parcel.setDataPosition(0);

    // Reconstruct object from parcel and asserts:
    Comment createdFromParcel = Comment.CREATOR.createFromParcel(parcel);
    assertEquals(test, createdFromParcel);
}

这会输出#define VarToStr(v) #v ... printf("%s\n", VarToStr(MatName)); 。但是现在让我们通过跨文件的函数来尝试这个(Matrix是一个已定义的类型):

MatName

这会输出// DebugHelpers.h #define VarToStr(v) #v ... void PrintMatrix(const Matrix &InputMat) { printf("%s\n", VarToStr(InputMat)); ... // output InputMat contents } // DataAnalysis.cc #include DebugHelpers.h ... void AnalysisSubProgram342() { Matrix MatName; ... PrintMatrix(MatName); } ,而不是InputMat。另一个文件中的函数如何从调用文件中获取变量名?

虽然更复杂的解决方案(包装类等)对更大的社区有用,但我的实现需要尽量减少对先前存在的代码/类的影响。

更新

受到天顶评论的启发,我实施了他提出的两个解决方案,以便进行比较,并且快速完成工作。该宏适用于简单输出,而该功能允许更复杂的工作(以及类型检查/重载)。我不知道预处理器宏可能如此复杂。我记得两者都是为了将​​来使用。谢谢!

3 个答案:

答案 0 :(得分:9)

你做不到。 C和C ++都不会在运行时保留变量名。

你所做的所有宏都是替换在编译时发生的文本。

答案 1 :(得分:4)

正如其他人所提到的,C ++不支持运行时反射,所以如果你想要一个字符串,其内容只能在运行时知道(即调用PrintMatrix时),你需要将其作为参数传递

因为你总是知道你的变量是什么'您不需要VarToStr宏名称

// DebugHelpers.h
void PrintMatrix(const Matrix &InputMat, const char* MatName)
{
    printf("%s\n", MatName);
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName, "MatName");
}

但是还有另一种选择:make PrintMatrix一个宏本身,因为它无论如何只是一个调试的东西:

// DebugHelpers.h
#define PRINT_MATRIX(InputMat)\
printf(#InputMat "\n");\
... // output InputMat contents


// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PRINT_MATRIX(MatName);
}

现在预处理后,AnalysisSubProgram342将如下所示:

void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    printf("MatName\n");
    ... // output InputMat contents
}

答案 2 :(得分:1)

一般情况下,你不能这样做(在运行时获取变量的名称,例如从其地址或在C ++中获取它的引用)。

我专注于Linux:

但是,在Linux(和基于GNU glibc的系统)上,对于全局变量(和函数),您可以使用GNU特定的dladdr(3)函数。

如果使用-g编译了所有相关代码(以获取调试信息),则可能会以DWARF格式解析调试信息(也许还使用__builtin_frame_address等)。有些痛苦,您可以从call stack的地址获取一些局部变量的名称。这将是一项重大的努力(可能是几个月的工作)。 Ian Taylor的libbacktrace(GCC内部)可能是一个有用的起点。

您也可以开始(假设所有内容都使用-g编译),例如popen(3)gdb -p调试过程。

请注意,最近的GDB调试器可以在Python或Guile中编写脚本,因此实际上,为GDB开发Python或Guile函数会更快。

您也可以简单地添加调试输出,如here