在函数内部使用时可变未声明的错误

时间:2017-01-13 12:03:16

标签: c macros

当函数fun()在main()上面定义时,变量'a'不能通过预处理器宏解析,但在main()下定义时工作正常。

#include <stdio.h>

void fun()
{
    printf("%d",a);
}

int main()
{
    #define a 5
    fun();
    return 0 ;
} 

背后的原因是什么?我们怎样才能使它工作,这样我就不必移动函数fun()定义。

4 个答案:

答案 0 :(得分:5)

C预处理器运行自上而下并替换#define s(&#34;文本替换&#34;)。因此,当#define a 5中的main()时,它可以“返回”#34;并替换a中的func();它只能替换a以下的#define,如果有的话。

您只需要在func()上方定义它。

来自C11 draft, 6.10.3 Macro replacement

  

表单

的预处理指令
# define identifier replacement-list new-line
     

定义一个类似于对象的宏,导致每个后续实例   要替换的宏名称 171 )   构成其余部分的预处理令牌列表   指示。然后重新扫描替换列表以获取更多宏名称   如下所述。

自标准前C以来,情况相同。来自Dennis Ritchie's C Reference Manual

  

12.1令牌替换格式为

的编译器控制行      

#define identifier token-string

     

(注意:没有尾随分号)会导致预处理器被替换   具有给定字符串标记的标识符的后续实例   (编译器控制线除外)。替换令牌字符串   有评论从中删除,它被空白包围。没有   尝试重新扫描替换字符串。

强调我的)。

答案 1 :(得分:4)

当然,在定义预处理器宏之前,你不能引用预处理器宏,而不是它的工作方式。

没有&#34;变量&#34;在这里,你对这个词的使用非常混乱。预处理器只是进行文本替换,编译器永远不会看到a符号,而是会看到5(如果定义了宏)。

我不知道如何让它发挥作用&#34;因为目标很奇怪。如果要访问全局变量,请使用:

#include <stdio.h>

int fun(int x)
{
    extern int a;
    return a + x;
}

int a = 12;

int main(void) {
    printf("a=%d, fun() returned %d\n", a, fun(11));
    return 0;
}

此处extern让我们在a之后定义fun(),但它不能在main()内。

答案 2 :(得分:3)

预处理器将在宏定义之后将a的任何实例替换为5。您可以将#define行放在函数上方。

作为旁注,void fun() { printf("%d", 5); } 不是变量,预处理器只会在编译之前进行文本替换。

会改变乐趣
{{1}}

答案 3 :(得分:3)

预处理步骤在编译步骤之前完成。而且,预处理器不知道C;对于预处理器,源文件只是文本。

在您的示例中,函数fun()中使用的符号a在使用前未声明,这是一个错误。在fun()的预处理器定义中,有一点无关紧要。由于定义更进一步,它不适用于<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:layout_width="match_parent" android:layout_height="match_parent" android:fillAfter="true"> <translate android:fromXDelta="-4%p" android:toXDelta="4%p" android:repeatCount="2" android:repeatMode="reverse" android:duration="10" /> </set> 的主体:永远记住,对于proeprocessor,源文件只是文本,它不知道C.预处理指令适用于它们出现在的位置文字,从未有过。

相关问题