【问题标题】:What is the Action of #define in this Instance?#define 在这个实例中的作用是什么?
【发布时间】:2019-10-04 09:58:23
【问题描述】:

作为我家庭作业的一部分,我得到了这段代码来帮助完成他们交给我们的任务……创建一个支持管道、后台进程和许多内置命令等的基本 shell。我已经阅读了他们提供给我们的用于解析的代码...

我对 C 语言中的 #define 关键字很熟悉,但是,我还没有看到它在下面的代码中使用过:也就是说,c 是干什么用的?我猜它已被指定为一个字符,但我不确定:

#define PIPE  ('|')
#define BG    ('&')
#define RIN   ('<')
#define RUT   ('>')

#define ispipe(c) ((c) == PIPE)
#define isbg(c)   ((c) == BG)
#define isrin(c)  ((c) == RIN)
#define isrut(c)  ((c) == RUT)
#define isspec(c) (ispipe(c) || isbg(c) || isrin(c) || isrut(c))

非常感谢任何帮助或建议。

【问题讨论】:

    标签: c++ c function shell


    【解决方案1】:

    您给出的最后五个#define 语句定义了,每个语句都有一个参数,即这里总是叫c。从技术上讲,您的前四个 #define 语句也是宏,但它们不需要参数 - 它们只是在遇到时替换它们的“值”;通常,程序员将不带参数的宏称为 tokens,这里的 PIPE 令牌具有 ('|') 的令牌值。

    稍后在文件中(可能)会出现调用这些宏中的一个或多个的情况,并且该调用将具有 actual 参数的值,例如:

    if (ispipe(test_arg)) ++npipes;
    

    这个宏“调用”将被(由预处理器)替换为以下扩展:

    if (((test) == ('|')) ++npipes;
    

    同样,对于其他 #define XXX(c) 宏。

    注意:在宏定义中添加(大量)括号是很常见的,只是为了确保代码在预处理器完成其工作后执行您“认为”的操作。 em>

    随时要求进一步解释和/或澄清。

    【讨论】:

    • C 标准中使用的术语是前四个#define 语句定义object-like 宏,后五个定义function-like 宏。虽然宏的名称在 C 语法中是一个记号,但我从未听过程序员将宏(不仅仅是它的名称)称为记号。
    • @EricPostpischil 也许对于我开发 C/C++ 编程技术的地点和/或与谁来说,这种用法是(或曾经是)口语化的。但也请参阅:google.co.uk/…
    • @Adrian:链接定义的含义 3 是我和 Eric(可能是大多数程序员)在这种情况下如何理解“令牌”这个词。 PIPE 一个令牌,但3+(printf 也是如此——这与它们是否是宏无关。
    【解决方案2】:

    #define 不是一个函数,它是一个预处理指令

    c 可以是任何东西。如果你写ispipe(42),那么预处理器会把它改成((42) == PIPE)。如果你写ispipe(while(1);),那么预处理器会把它改成((while(1);) == PIPE),这会让编译器在读取的时候傻眼。

    预处理器是盲目的,对C语法知之甚少,对它的语义一无所知;理解c 应该是什么的唯一方法是对预期用途进行逆向工程,或者询问编写代码的人没有 cmets 告诉你它们的意思。

    编辑后,可以合理地预期c 应该是char,以便与'|' 等进行有意义的比较。但即使通过0xDEADBEEF 也应该正确编译(返回FALSE)。

    【讨论】:

    • 预处理器对 C 语法一无所知是不正确的。它知道足够的语法来识别 C 语法的预处理标记(例如标识符、常量、字符串文字和标点符号),并且它通过替换预处理标记而不是文本来工作。
    • @Amadan:根据 2018 C 标准及之前的版本,预处理标记的语法是 C 的正式一部分。它在标准的第 6.4 条中定义,如果违反句法规则,则在预处理期间会出现错误。预处理也是 C 的正式一部分,并在第 610 条中定义。如果尝试单独使用预处理器(如gcc -x c -E)来处理非 C 文件,则可以观察到这一点。例如,#define cannot can't 会产生错误。
    猜你喜欢
    • 1970-01-01
    • 2014-03-31
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    • 2019-08-13
    • 2012-11-20
    相关资源
    最近更新 更多