16

I do not understand the macro concept well. What is a macro? I do not understand how is it different from function? Both function and macro contain a block of code. So how does macro and function differ?

  • 15
    Are you referring to any particular programming language? – mkrieger1 Jun 24 at 11:51
  • 15
    You need to be more specific; macro refers to three very different concepts, roughly C-style text/preprocessor macros, Lisp macros, and application macros. – chrylis Jun 24 at 14:03
6

Note

I would like to add the following clarification after observing the polarising voting pattern on this answer.

The answer was not written keeping technical accuracy and broad generalization in mind. It was a humble attempt to explain in simple language, difference between macros and functions to a programming newbie, without trying to be complete or accurate (in fact it's far from being accurate). C programming language was in my mind when drafting the answer, but my apologies for not mentioning it clearly and causing any (potential) confusion.

I really regard the answer shared by Jörg W Mittag. It was insightful reading it (how less I know) and I upvoted it soon after it was posted. I just got started on Software Engineering Stack Exchange, and the experience and discussions so far have been really insightful.

I will leave this answer here as it may be helpful for other software development newbies, trying to understand a concept without getting bogged down into technical accuracies.


Both macro and function represent self contained unit of code. They both are tool which aid in modular design of a program. From the point of view of the programmer who's writing the source code, they appear quite similar. However, they differ in how they are handled during the program execution lifecycle.

A macro is defined once and used in a lot of places in a program. Macro gets expanded inline during the pre-processing stage. Thus, it technically doesn't remain a separate entity once the source code is compiled. The statements in macro definition becomes part of program instructions, just like other statements.

The motive behind writing a macro is to make writing and managing source code easier for the programmer. Macros are generally desired for simpler tasks where writing a full-fledged function would be a performance overhead/runtime penalty. Examples of situations where a macro is preferable over function are:

  • Using constant values (such as mathematical or scientific values), or some program specific parameter.

  • Printing log messages or handling assertions.

  • Performing simple calculations or condition checks.

When using macro, it's easy to make changes/corrections in one place which are instantly available everywhere the macro is used in the program. A simple recompilation of program is required for the changes to take effect.

Function code on the other hand is compiled as a separate unit within the program and gets loaded in the memory during program execution only if it's required. The function code retains it's independent identity from the rest of the program. The loaded code gets reused if the function is called more than once. When the function call is encountered in the running program, the control is passed to it by the runtime subsystem and the context of the running program (return instruction address) is preserved.

However, there's a slight performance penalty that needs to be encountered when calling a function (context switching, preserving return address of the main program instructions, passing parameters and handling return values etc.). Hence, the use of function is desired only for complex blocks of code (against macros which handles simpler cases).

With experience, a programmer makes a judicious decision as whether a piece of code will be a good fit as a macro or function in the overall program architecture.

  • 9
    What about function inlining? – Nathan Cooper Jun 24 at 10:41
  • 1
    In the C language & co a macro can be a function call too. So making a distinction between the two doesn't make much sense. – Sombrero Chicken Jun 24 at 12:11
  • 5
    And C-style macros are anything but self-contained - they don't introduce a lexical scope, and have unlimited access to local names in scope at the point of substitution. – Useless Jun 24 at 13:18
  • @Sombrero Chicken: Perhaps you could show an example of that? You can have macros which CONTAIN function calls, but (AFAIK) the macro is not a function call. – jamesqf Jun 24 at 16:52
  • 3
    There are many things about this answer which are misleading. The examples you mention are absolutely not in any way whatsoever situations where macros are 'preferable' - quite the opposite in fact. Macros shouldn't be used for those things unless there's an extremely good reason to. Performance is generally not a good rationale for using macros at all. For reasons mentioned in other comments, justifying the use of macros in this way is likely to result in to error-prone code with all manner of unintentional consequences, particularly in a larger codebase. – Ben Cottrell Jun 24 at 20:07
64

Unfortunately, there are multiple different uses of the term "macro" in programming.

In the Lisp family of languages, and languages inspired by them, as well as many modern functional or functional-inspired languages like Scala and Haskell, as well as some imperative languages like Boo, a macro is a piece of code that runs at compile time (or at least before runtime for implementations without a compiler) and can transform the Abstract Syntax Tree (or whatever the equivalent in the particular language is, e.g. in Lisp, it would be the S-Expressions) into something else during compilation. For example, in many Scheme implementations, for is a macro which expands into multiple calls to the body. In statically-typed languages, macros are often type-safe, i.e. they cannot produce code that is not well-typed.

In the C family of languages, macros are more like textual substitution. Which also means they can produce code that is not well-typed, or even not syntactically legal.

In macro-assemblers, "macros" refer to "virtual instructions", i.e. instructions that the CPU does not support natively but that are useful, and so the assembler allows you to use those instructions and will expand them into multiple instructions that the CPU understands.

In application scripting, a "macro" refers to a series of actions that the user can "record" and "play back".

All of those are in some sense kinds of executable code, which means they can in some sense be viewed as functions. However, in the case of Lisp macros, for example, their input and output are program fragments. In the case of C, their input and output are tokens. The first three also have the very important distinction that they are executed at compile time. In fact, C preprocessor macros, as the name implies, are actually executed before the code even reaches the compiler.

  • 1
    “In statically-typed languages, macros are often type-safe, i.e. they cannot produce code that is not well-typed” – really? What languages are you referring to? AFAICS, this is in general only possible to guarantee in a dependently-typed language. In Haskell, TH macros are only syntactically safe, but the type checker runs afterwards. (So type-wise, they give even fewer guarantees than C++ templates do). – leftaroundabout Jun 24 at 14:30
  • 1
    Other than application scripting, I don't think the three examples you give are all that different. All perform a substitution of some sort into the program, as opposed to jumping into a shared piece of code when its executed. – IMSoP Jun 24 at 15:46
  • Maybe you can extend the mention of C's macros with the general concept of macro languages like M4, since for C it's basically that the spec defines a CPP auxiliary macro language and standardizes its use with C. – JoL Jun 24 at 21:15
  • 1
    The general theme seems to be that macros generate code to be interpreted as part of a larger program's source code, rather than getting executed when the program is run. – jpmc26 Jun 24 at 22:07
  • 1
    @jpmc26 I'd say the general theme is substitution where you do a small thing and it expands to a big thing. The macro language M4 isn't particularly meant for code. You can use it to generate any text. There's also keyboard macros, like this answer mentioned. You hit 1 or 2 keys and they expand to a greater amount of keypresses. vim macros are like that too. Save a large sequence of normal mode commands under a single key, and you call that sequence by running the normal mode command that executes it. – JoL Jun 25 at 1:23
2

In the C language family a macro definition, a preprocessor command, specifies a parametrized template of code that is substituted at the macro call without being compiled at the definition. This means that all free variables should be bound in the context of the macro call. Parameter arguments with a side effect like i++ could be repeated, by plural usage of the parameter. The textual substitution of argument 1 + 2 of some parameter x happens before compilation, and might cause unexpected behavior x * 3 (7 i.o. 9). An error in the macro body of the macro definition will show only upon compilation at the macro call.

The function definition specifies code with free variables bound to the context of the function body; not the function call.

The macro however seemingly negative provides access to the call, the line number and source file, the argument as string.

0

A macro generally refers to something that is expanded in place, replacing the macro "call" during compilation or pre-processing with individual instructions in the target language. At runtime, there will generally be no indication of where the macro begins and ends.

This is distinct from a subroutine, which is a reusable piece of code which is located separately in memory, to which control is passed at runtime. The "functions", "procedures", and "methods" in most programming languages fall into this category.

As Jörg W Mittag's answer discusses, the exact details vary between languages: in some, such as C, a macro performs text substitution in the source code; in some, such as Lisp, it performs manipulation of an intermediary form like an Abstract Syntax Tree. There are also some grey areas: some languages have notation for "inline functions", which are defined like a function, but expanded into the compiled program like a macro.

Most languages encourage programmers to reason about each subroutine in isolation, defining type contracts for inputs and outputs, and hiding other information about the calling code. There is often a performance impact to calling a subroutine which macros do not incur, and macros may be able to manipulate the program in ways that a subroutine cannot. Macros may therefore be considered "lower level" than subroutines, because they operate on a less abstract basis.

2

In slightly more abstract terms, a macro is to syntax as a function is to data. A function (in the abstract) encapsulates some transformation on data. It takes its arguments as evaluated data, performs some operations on them, and returns a result which is also just data.

A macro in contrast takes some unevaluated syntax and operates on that. For C-like languages, the syntax comes in at the token level. For languages with LISP-like macros, they get the syntax represented as an AST. The macro must return a new chunk of syntax.

0

Macro is executed during compilation, and function is executed at run time.

Example:

#include <stdio.h>

#define macro_sum(x,y) (x+y)

int func_sum(x,y) {
    return x+y;
}

int main(void) {
    printf("%d\n", macro_sum(2,3));
    printf("%d\n", func_sum(2,3));
    return 0;
}

So during compilation the code is actually changed to:

#include <stdio.h>

int func_sum(x,y) {
    return x+y;
}

int main(void) {
    printf("%d\n", (2+3));
    printf("%d\n", func_sum(2,3));
    return 0;
}

protected by gnat Jun 25 at 3:14

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.