在C语言中,宏和函数有什么区别?

20
C中宏与函数的区别是什么?请告诉我一个可用宏和函数的应用场景。

6
你要求“一个可以使用宏和函数的应用程序”的唯一原因是因为这是一项作业。为什么不自己尝试做呢?请注意,我只会翻译,不会提供解释或其他内容。 - David Heffernan
6个回答

21

基本的区别在于函数是编译过程中处理的,而宏是预处理过程中处理的。当你使用函数调用时,它将被翻译成带有所有这些堆栈操作以传递参数和返回值的ASM CALL。当你使用宏时,C预处理器将使用宏来翻译所有字符串,然后进行编译。

使用宏的缺点是它们隐藏了实现细节。如果有错误,那么查找起来会更加困难。


11

C 和 C++ 中,宏是预处理器指令。这意味着在程序开始编译之前,将会遍历并处理所有宏定义。宏定义有用的原因是:

  • 可以使你的程序更易读
  • 可以提高效率 (因为它们可以在编译时计算)
  • 可以缩短长或复杂的表达式,特别是重复使用的表达式。例如,我们使用一个宏来获取当前的log4cpp记录器,并使用另外几个宏以不同的级别写入它。

缺点

  • 会增加可执行文件的大小
  • 如果不小心使用过多预处理器宏,可能会淹没您的名称空间。例如,如果您有太多的预处理器宏,则可能会在代码中意外使用它们的名称,这可能非常难以调试。

示例:

#define INCREMENT(x) x++

函数是一段代码,可以相对独立地执行并执行特定的任务。您可以将其视为数学函数的一种:给定一组输入,函数将给出一个特定的输出。在C语言中,这些被定义为

<return type> <name>(<parameters>)
{
  //code body
}

1
你必须将宏想象成文本替换:就像在代码中每次看到宏时都内联宏代码一样。这对于“代码片段”很有好处,因为你避免了函数调用开销,因为每次调用函数时,你都需要花费一些精力将参数推入堆栈。

是的,内联函数在这方面更好。 - Almo

1
另一个区别是,在函数中存在堆栈开销,但在宏的情况下不存在堆栈开销;它只是代码的扩展。

2
如果该函数被内联,就不会有堆栈开销。 - EfForEffort

-1

函数是从的操作,即程序通常处理的数据类型(数字、字符串等)。

宏是从代码代码的操作。它获取程序的一部分并使用它来生成程序的另一部分。

C语言中函数和宏之间完全没有重叠;它们不做相同的事情。(您不能编写从值到代码的函数;尽管外观上看起来可以编写从代码到值的宏,但重要的是要理解这实际上不是您正在做的事情。)

宏可以被制作成类似于函数的形式,因为你可以编写一个宏来处理生成或表示值的代码片段,但是该宏仍然不会操作值本身:它将“生成值的代码”(可能是一个简单的数字)编织到“消耗值的代码”中(这就是宏的“主体”所看起来的东西)。这意味着像函数一样使用宏非常令人困惑,也不是宏最好的用法。相比之下,函数实际上是一个单独的离散代码块。

函数通常在运行时运行,而宏(在C中)始终在编译时运行,这只是由于值通常是动态的,而代码通常在运行时不可用的限制所导致的。这实际上并不是函数或宏的基本特征(函数可以内联和优化掉;宏可以应用于动态生成的代码),并且有点误导性。


1
这个答案非常混乱。它让人更加困惑而不是启发。 - John Kugelman
@JohnKugelman,那有什么不清楚的地方吗?我该怎么让你更明白呢?对我来说,它似乎已经很清楚了,否则我就不会这样写了,而且它在技术上是正确的,这比这个问题中的一些现有答案要好得多。是啊,没错,这是一个老问题,当我回答时没有注意到,抱歉。它仍然为问题提供了不同的材料。关注编译时/运行时或机器码/文本的答案是错误的,它们描述了实现但是忽略了重点。 - Alex Celeste
(a) 一个函数不严格地说是从值到值的操作;那是数学定义。函数有副作用,它们不仅仅是映射。并且它们不需要返回一个值。(b) 说宏是“从代码到代码的操作”是描述宏的一种令人困惑的方式。我会用“文本替换”来解释宏。(c) 函数与类似函数的宏之间有很大的重叠。声称它们在目的上没有重叠真的很奇怪。宏的一个主要用途是强制内联本应放在函数中的代码。 - John Kugelman
1
函数和类似函数的宏之间在目的上完全没有重叠,我坚持这一点。在使用上有重叠(这个问题的存在就很明显),但它们并不做同样的事情。宏永远不能将2和2相加得到4,它只能将22相加得到2+2这是核心区别。绝对所有其他内容都是附带的/实现细节/特定于C 文化。相反,暗示宏和内联之间的任何关系都是混淆这个主题的例子。 - Alex Celeste

-2
宏的优点在于我们只需要定义一次,如果我们想要更改值,只需在一个地方进行更改,该值将在整个程序中得到反映。

这不是问题的答案! - Gamal Othman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接