如何访问被宏定义隐藏的全局变量?

时间:2018-08-21 04:39:50

标签: c macros

是否可以在全局范围内访问(自引用)宏中使用的变量? 我使用的是用于指代此类宏的术语。
参见gcc.gnu.org/onlinedocs/cpp/Self-Referential-Macros.html
我的示例代码基于此处显示的示例代码。

简单示例:

#include <stdio.h>

int foo = 10; /*A variable at global scope. There may be a few of these.*/

#define foo (4 + foo) /*A self-referential macro. There may be a few of these.*/

int main()
{
    printf("foo = %d\n", foo); /*Prints 14. The value after the macro expansion */  

    /*Is there any way to access the global variable *foo* here?*/  

    return 0;
}

3 个答案:

答案 0 :(得分:4)

是的,您可以使用#undef foo删除宏定义。

答案 1 :(得分:2)

  

是否可以在全局范围内访问自引用宏中使用的变量?

不,不是。 FWIW,将全局变量重新定义为self-referential宏非常丑陋,而且味道很差,并且使代码无法读取。不要那样做。

了解有关C语言中各种translation phases的更多信息(后来,也请参考C11标准n1570)。 Preprocessing在概念上发生在实际解析之前。

实际上,不要#define foo,例如#define FOO_MAC并适当地使用FOO_MACfoo(就像Eric Postpischil的answered一样,您可以改用#undef,但这会使代码的可读性降低)。< / p>

顺便说一句,您可以获取预处理的表单(作为文本文件)。使用GCC时,invoke it

gcc -Wall -C -E yourfoocode.c > yourfoocode.i

然后在页面yourfoocode.i中使用分页器或编辑器进行浏览

也请阅读documentation of cpp

特别是对于GCC,您还可以在全局变量声明中使用asm labels(例如int otherfoo asm ("foo");)来声明位于同一位置的另一个变量。但这会使读者感到困惑,并且可能会使编译器的优化过程不高兴(例如,&foo != &otherfoo可能被优化为true,但为false),所以您不想这样做。

请注意,C编程需要大量良好的约定和样​​式才能具有可读的代码,因此在实践中,您要求从不发生。这样做时,您需要重写代码(仅出于可读性原因)。

答案 2 :(得分:2)

代码是可读性和可维护性的负担。
我希望您只是在问这个问题,因为这是您必须应付的一些旧代码,我对您有感觉。

我想您将最接近访问全局变量,对显示的代码进行的更改最少,并且不添加其他代码文件,

#include <stdio.h>

int foo = 10; /*A variable at global scope. There may be a few of these.*/
int* backdoorfoo = &foo;

#define foo (4 + foo) /*A self-referential macro. There may be a few of these.*/

int main()
{
    printf("foo = %d\n", foo); /*Prints 14. The value after the macro expansion */  

    printf("foo = %d\n", *backdoorfoo); /*Prints 10, via dereferencing the differently named pointer. */  

    return 0;
}

请注意,使用#undef也是一种可行的解决方案,但我认为,这只会使事情变得比现在更糟。

如果您根本无法更改可怕的代码但被允许添加代码文件,则可以选择利用foo是全局的这一事实。
它允许从第二个代码文件访问实际的全局变量,该文件不包含宏障碍。

main.c:

#include <stdio.h>

int foo = 10; /*A variable at global scope. There may be a few of these.*/

#define foo (4 + foo) /*A self-referential macro. There may be a few of these.*/

void printfoo(void); /* only needed for demo */
int main()
{
    printf("foo = %d\n", foo); /*Prints 14. The value after the macro expansion */

    printfoo(); /* Only needed for demo. Prints 10, the value of global foo variable.  */

    return 0;
}

second.c:

#include <stdio.h>

extern int foo;

void printfoo(void)
{
        printf("foo = %d\n", foo); /*Prints 14. The value after the macro expansion */
}