【问题标题】:Output file of the C PreprocessorC 预处理器的输出文件
【发布时间】:2021-02-12 12:10:23
【问题描述】:

理论问题: C 预处理器的语言格式到底是什么。我知道它的作用,它的用途,当它被调用时,但如果它的输出是:a)汇编代码,b)C源代码(据说它看起来像它)或c),我无法找到任何地方机器语言(我不认为这是它,而是一个猜测)。

【问题讨论】:

  • C 预处理器只进行文本替换。输出对应于输入,即预处理器宏和输入文件中的其他文本。
  • 输入:C源代码;输出 C 源代码,移除 cmets(替换为空格)和“一些”其他调整
  • 你检查过它的输出吗?这清楚了很多。就像在 Linux 上一样,您可以执行 gcc -E some-file.c 。
  • 或者在 Windows Mingw gcc -E main.c > pp.c 然后gcc pp.c -osomething.exe
  • @Bodo:C 预处理器替换预处理器标记,而不是文本,它还具有连接、字符串化、条件和无条件包含、报告错误、控制浮点环境和复杂算术等功能,以及编译器扩展为 C。

标签: c output c-preprocessor


【解决方案1】:

当预处理被集成到 C 编译器中时,它在编译器中的输出可能是预处理器标记和空白序列的形式,这两种形式都是有效的字符序列,以任何方式在编译器内部表示设计师选择。 (例如,输入文本int main(void) 的标记将是int main(void)。)

当预处理器输出写入文件时,它是带有空格字符的文本,根据需要来分隔标记。此输出是无需进一步预处理即可编译的源代码;您可以像处理普通 C 源代码一样将其提供给 C 编译器。但是,它可能包含其他非标准文本以支持编译器功能,例如 # 行,其中包含有关原始源文件名和行号的信息。

【讨论】:

    【解决方案2】:

    理论问题:C 预处理器的语言格式到底是什么。我知道它的作用,它的用途,当它被调用时,但如果它的输出是:a)汇编代码,b)C源代码(据说它看起来像它)或c),我无法找到任何地方机器语言(我不认为这是它,而是一个猜测)。

    嗯,它是一个与 C 编译器相关的 预处理器...任何地方都可能需要搜索的地方太多了:必须为每个编译器在编译器中记录它选项,所以它必须是一个搜索的地方

    预处理器不是编译器,预处理器只知道文本。它接收文本,输出文本,截取以# 开头的内容并执行它的操作。就像nroff 一样。

    因此预处理器输出没有语言格式:它只是文本

    在 Windows 上使用 gcc 10.2 的示例

    搜索gcc preprocessor output option会在第一页得到这个

    无论如何引用gcc docs

    如果您使用 -E 选项,则除了预处理之外什么都不做。其中一些选项只有与 -E 一起使用才有意义,因为它们会导致预处理器输出不适合实际编译。

    文件 pp1.h

    // pp1.h
        int x = 300;
    // end of pp1.h    
    

    文件 pp2.h

    // pp2.h
        return 
    // end of pp2.h    
    

    文件 pp.c

    #include "pp1.h"
    
    int main(void)
    {
                    #include "pp2.h" 
        x;
    }
    // end of pp.c
    

    gcc -E pp.c 的输出

    # 1 "pp.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "pp.c"
    # 1 "pp1.h" 1
    
        int x = 300;
    # 2 "pp.c" 2
    
    int main(void)
    {
    # 1 "pp2.h" 1
    
        return
    # 6 "pp.c" 2
        x;
    }
    

    由于 -E 选项,代码没有被编译,但它肯定是有效的 C,因为这是我们一直在做的事情:使用一些 #define,一些 #include 并编译我们的代码。
    我们可以将它再次通过管道传递给 gcc,并像往常一样使用生成程序

        gcc -E pp.c | gcc -o pp.exe -xc -
    

    然后像往常一样运行程序:

    C:\src>pp
    
    C:\src>echo %ERRORLEVEL%
    300
    
    

    对通用文本使用预处理器

    当然,用处不大,但只是作为案例的 5 分钟说明,这里的 t1.txt 是城市列表:

    t1.txt

    #include "t1.h"
    
    Microsoft Corporate Offices Addresses(where found)
    
    Austin
    Costa Mesa
    Houston 
    Nashville
    Memphis
    Mountain View
    

    t1.h

    标题有城市和地址列表

    #define    Nashville \
        Nashville: Corporate Sales Office \
        8 City Boulevard, Suite 403 \
        Nashville, TN, USA \
        37209
    
    #define     Memphis \
        Memphis: Corporate Sales Office \
        6465 N. Quail Hollow Road, Suite 200 \
        Memphis, TN, USA \
        38120
    
    #define     Houston \
        Houston: Corporate Sales Office \
        750 Town and Country Boulevard, St. 1000 \
        Houston, TX, USA \
        77024
    // end of t1.h
    

    预处理器输出

    这个命令

    gcc -E -x c t1.txt | grep -v "^#"
    

    在 gcc 10.2 下显示

    
    Microsoft Corporate Offices Addresses(where found)
    
    Austin
    Costa Mesa
    Houston: Corporate Sales Office 750 Town and Country Boulevard, St. 1000 Houston, TX, USA 77024
    Nashville: Corporate Sales Office 8 City Boulevard, Suite 403 Nashville, TN, USA 37209
    Memphis: Corporate Sales Office 6465 N. Quail Hollow Road, Suite 200 Memphis, TN, USA 38120
    Mountain View
    

    输出显而易见:当在列表中找到办公室地址时,将其附加到城市。

    只是一个玩具。预处理器不懂编程语言。

    【讨论】:

    • Re “所以预处理器输出没有语言格式:它只是文本”:预处理器有语言格式。它在 C 2018 6.10 1 中指定,并引用了 6.4 1、6.4.2.1 1 和 6.6 1 中定义的语法标记,后者与 C 表达式语法的大部分内容相关联。例如,它不是非结构化文本,预处理器错误将由格式错误的标记、未终止的#if 指令和#if 语句中的格式错误的表达式引起。
    • ISO 是迂腐的。您可以使用预处理器来预处理常规的非 C 文本,无论如何它都会完成它的工作......我认为如果您花时间这样做,我认为没有必要对我的答案投反对票。像我一样写一个测试...
    • 没有人否决您的答案,您不能使用预处理器来预处理常规的非 C 文本。前段时间,我想在包含多行引用文本的文本上使用它,这在英文文本中是正常的,但由于我所说的问题,它不能用于此目的。这不是迂腐;这是一个依赖于预处理规范的真实用例。这个答案不必要地做出虚假陈述。
    • 一件事是“包含多行引用文本的文本,这在英文文本中很正常”另一件事是文本,另一件事是 C。我说在这种情况下 C 标准是迂腐的。再次引用您的话:“依赖于预处理规范的实际用例”对每个预处理器都有效......我将在我的答案中插入一个无用的例子,@EricPostpischil
    • “不必要地做出虚假陈述”对我的帖子@EricPostpischil 来说听起来有点粗鲁
    猜你喜欢
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多