宏模板和扩展

时间:2014-05-11 04:09:19

标签: c gcc macros

  

考虑以下计划。

  

Practice.c

#include <stdio.h>
#define P(x,y,z) (x+y+z) 

main()
{
  int x,y,z,i,j,k;

  printf("\n  Number I = ");
  scanf("%d",&i);
  printf("\n Number II = ");
  scanf("%d",&j);
  printf("\nNumber III = ");
  scanf("%d",&k);

  printf("\n    Result = %d\n",P(i,j,k));
}

现在,如果我运行gcc -E Practice.c,那么输出将是

# 2 "Practice.c" 2


main()
{
  int x,y,z,i,j,k;

  printf("\n  Number I = ");
  scanf("%d",&i);
  printf("\n Number II = ");
  scanf("%d",&j);
  printf("\nNumber III = ");
  scanf("%d",&k);

  printf("\n    Result = %d\n",(i+j+k));
}
  

在此处, P(i,j,k)(i+j+k)取代,并且在命令屏幕上清晰可见。

我的问题是,#include <stdio.h>在这里究竟发生了什么?

它是否也被stdio的文件替换,与#define P(x,y,z) (x+y+z)的方式相同,或者它只是将stdio的内容链接到main()的方式

而且,使用# 2 "Practice.c" 2之后输出中的gcc -E Practice.c是什么?

3 个答案:

答案 0 :(得分:1)

在预处理期间,#include指令实际上被包含文件的内容替换。此外,包含文件本身是预处理的,因此如果它包含任何其他include指令,则包含另一个文件等。

非常通常,预处理器和编译器是两个不同的程序,预处理的输出通过管道发送到编译器。编译器本身不会打开和读取源文件。

在这种情况下,很明显必须有一种机制,预处理器如何告诉编译器代码的来源。这对于错误消息是必需的。如果存在语法错误,则预处理器不会检测到它,编译器会找到它,并且编译器需要显示错误所在的确切行和源文件。但是,当只从管道中读取一个流时,如果没有其他形式,则无法获取此信息。这就是为什么像

这样的行
 # 2 "Practice.c" 2

出现。它是关于源代码的实际来源的信息。在这种情况下,预处理器通知该行后面的代码来自文件&#34; Practice.c&#34;下一行是此源代码的第二行。然后编译器可以增加下一行序列的行号,直到下一个这样的指令(通常被称为#line指令)。

答案 1 :(得分:0)

预处理程序指令#define用于宏扩展。指令#include用于包含头文件。所以#include <stdio.h>将标准头文件的内容放到当前文件中。您可以比较源文件和预处理文件,以查看标题stdio.h中的内容。

答案 2 :(得分:0)

首先,头文件只是一个文本文件,其中包含原型(函数声明)和许多其他内容。 (IMP:Headers文件只有声明而非定义)。

简单来说,#include<stdio.h>表示将stdio.h文件中的所有内容插入/包含在源代码文件中。这里< >表示stdio.h文件存在于编译器已知的特殊文件夹中(其中包含许多其他头文件)

如果你写#include"stdio.h",这意味着将stdio.h文件中的所有内容插入/包含在源代码文件中。但是这里" "表示stdio.h文件存在于您的practice.c所在的当前文件夹中。(因为它不是,如果您这样写,它将给出错误消息)

让我们通过一些“不那么实用”的程序来理解上述概念,假设我创建了一个名为myheader.h的文件,它有一些这样的文本。

<强> myheader.h

Hello am nothing untill am something......

现在我在practice.c中编写一个程序(出现在myheader.h文件所在的同一文件夹中)。

#include"myheader"
int main()
{
  return 0;
}

现在,如果我使用命令 gcc -E practice.c

编译(或者我应该只是说PreProcess)

输出

Hello am nothing untill am something......
int main()
{
  return 0;
}

将头文件的内容插入源文件称为文件包含。(与宏替换不同)

宏替换意味着用某种东西代替某种东西(你用#define P(x,y,z) (x+y+z)做的)。如果在许多程序中使用相同的宏,你可以做的是,你可以将这些宏写在一个单独的头文件中并将其包含在你的源文件中。就像你可以重用宏而不用写它们一次又一次在源文件中。

最后如果要正确查看Preprocessed输出,请使用此命令 gcc -E practice.c -o abc.txt 这将保存预处理<的所有输出/ strong>进入名为abc.txt文件的单独文件。打开 abc.txt 文件后,您会发现从stdio.h头文件插入abc.txt的代码行(超过100行), 您会发现许多常用的原型(声明),如printf()scanf()之类的函数,以及插入的更多(和其他内容),以及您的代码(你写的)将坐在文件的末尾。你必须向下滚动到最后才能看到你的代码。