-2

From what I understand about macros in C, they are predefined constants that will be used throughout the program with their constant value, so we go ahead and define them to avoid further complications and make the code more readable, so people reading it will understand what is supposed to stay constant and what isn't.

I have read here and there (C programming A Modern Approach, K.N King) that we can define these two functions as macro.

Since I'm somewhat new to C, I can't wrap my head around how can these two be defined as macro?

dbush
  • 205,898
  • 23
  • 218
  • 273
AliMan
  • 155
  • 7
  • 1
    [Functional macros in C](https://stackoverflow.com/questions/9104568/macro-vs-function-in-c) – kocica Aug 18 '17 at 15:44
  • *From what I understand about Macro's in C,they are predefined constants* - no, they are not. It is easy to figure out what they are by a simple google search. – Eugene Sh. Aug 18 '17 at 15:44

4 Answers4

5

There are two types of macros: simple substitution macros and function-like macros.

Substitution macros replace one instance of a symbol with another. For example:

#define LEN 10
char str[LEN];

After preprocessing, this becomes:

char str[10];

A function-like macro can take parameters that can be plugged in to whatever gets substituted:

#define MAX(a,b) ((a) > (b) ? (a) : (b))
int x = MAX(2,3);

After preprocessing:

int x = ((2) > (3) ? (2) : (3));

In the case of getchar and putchar, they can be defined as follows:

#define getchar() getc(stdin)
#define putchar(c) putc(c, stdout)
dbush
  • 205,898
  • 23
  • 218
  • 273
1

Fully depends on implementation. They can be function also.

Standards don't demand anything explicit about the type of implementation. But you can check here it points Any function declared in a header may be additionally implemented.... as pointed by Eugene.Sh

To say it more clearly, there may be a function in the library or it can be a macro also (for getchar). Classically, the macro for getchar() would be #define getchar() getc(stdin), and getc() might also be a macro.

Standard says that The getc function is equivalent to fgetc, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects.

Now it boilds down to fgetc in which case we know that it is guaranteed to be a function. Thread safety makes it more likely to be a function.

Community
  • 1
  • 1
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • What do you mean? – 0___________ Aug 18 '17 at 16:02
  • @PeterJ.: Ah that based on that there is no hard rule saying that getchar()` has to be macro or function. You can implement it on your own way. – user2736738 Aug 18 '17 at 16:04
  • Moreover, the standard is defining it as a function, without mentioning any `macro` word explicitly. – Eugene Sh. Aug 18 '17 at 16:08
  • @EugeneSh.: Yes I even checked that also some time ago..your point is right. – user2736738 Aug 18 '17 at 16:09
  • http://port70.net/~nsz/c/c11/n1570.html#7.1.4 is implicitly allowing a standard function to be implemented as macro. – Eugene Sh. Aug 18 '17 at 16:16
  • @EugeneSh.: I see. but it is really not an issue if you think that way. Standards don't demand anything explicit. – user2736738 Aug 18 '17 at 16:19
  • I didn't say it is an issue :) Just a bit of formalization. – Eugene Sh. Aug 18 '17 at 16:20
  • @EugeneSh. Ah should I add it to my answer? No it is helpful information truly. Thanks for letting me know. I am learning too. – user2736738 Aug 18 '17 at 16:21
  • Up to you, I guess.People here like having standard references as a proof of the answer. – Eugene Sh. Aug 18 '17 at 16:22
  • There must be a function in the library that does the job defined; there may also be a macro for it. Classically, the macro for `getchar()` would be `#define getchar() getc(stdin)`, and `getc()` might also be a macro. The standard says _The `getc` function is equivalent to `fgetc`, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects._ Note that `fgetc()` does not get that special exemption; it is classically only implemented as a function. Thread-safety makes it likely there's a function call. – Jonathan Leffler Aug 18 '17 at 17:08
  • @JonathanLeffler.: Right point. But I answered from the view point of these two functions. You can add your answer if possible otherwise if you permit I will add it later. – user2736738 Aug 18 '17 at 17:15
  • Add the material I wrote as you see fit with my blessing. But your answer doesn't yet distinguish well between object-like macros and function-like macros — and `getchar()` and `putchar()` are function-like macros. – Jonathan Leffler Aug 18 '17 at 17:24
  • @JonathanLeffler.: I will and let you know. – user2736738 Aug 18 '17 at 17:26
  • @JonathanLeffler.: Modiefied the answer. But let me know one thing...why do we need a function in case of thread safety not anything else? – user2736738 Aug 27 '17 at 03:13
  • 'Tis a long story — are you sitting comfortably? Once upon a threadless time, the `getc()` and `putc()` were primarily implemented as macros which usually didn't call a function at all. Then POSIX introduced thread-safety requirements, and in particular required `putc()` and `getc()` to achieve the effect of calling `flockfile()` and `funlockfile()` — which tends to mean that those functions are called, negating the "no calling of function" benefit for a macro. Of course, `getchar()` can be implemented as `#define getchar() getc(stdin)` still, but the `getc()` may not expand as a macro. – Jonathan Leffler Aug 27 '17 at 03:22
  • It all still depends on the implementation, which presumably has been optimized to the maximum extent. – Jonathan Leffler Aug 27 '17 at 03:23
  • @JonathanLeffler Thanks for the reply. Two things: 1. so can I say the reason that in order to be thread safety we need to call or use `flockfile` and `funlockfile` functions and it is not encouraged to have a function call in macro. So that's why we need a function to achieve thread safety? 2. In the last line you said "...getc() may not expand as macro"...getc is a macro in current implementations (most of them)? am I missing somehthing? – user2736738 Aug 27 '17 at 03:31
  • MacOS Sierra (BSD?) is an example of an implementation where `getc()` is not a macro (and neither is `getchar()`). You'd need to look at the expansion to see whether the expansion is thread-safe (and/or read the local documentation). – Jonathan Leffler Aug 27 '17 at 03:42
  • I used the code: `#include int get1(void); int get2(void); int get1(void) { return getchar(); } int get2(void) { return getc(stdin); }` and ran it through `gcc -E gc31.c` — and only needed to look at the last 20 lines or less. The output was `# 3 "gc31.c" int get1(void); int get2(void); int get1(void) { return getchar(); } int get2(void) { return getc( # 13 "gc31.c" 3 4 __stdinp # 13 "gc31.c" ); }` You can probably deduce where the newlines go. – Jonathan Leffler Aug 27 '17 at 03:52
  • @JonathanLeffler.: After only preprocessing I got something like `_IO_getc()` in case of second function. And I couldn't find the implemenattion of BSD.(maybe I should serach more) But to be honest I meed to get the answer of 1. why do you think a macro is unable to be thread safe? – user2736738 Aug 27 '17 at 04:13
  • Well, it could be converted to a macro, but the size of the macro and the performance because of embedded calls to ensure thread-safety mean that it is no longer a performance benefit. That's my assessment; someone else may have different views on it. – Jonathan Leffler Aug 27 '17 at 04:18
  • @JonathanLeffler macro is used for performance mostly. If that is compromised to obtain a thread safe version then I guess, macro is not that useful as it is supposed to. I guess..I won't add this detailed discussion in answer? Btw Thanks for the explanation. – user2736738 Aug 27 '17 at 04:21
1

There are basically three types of preprocessor macros:

  1. Simple defined without any value. For example

    #define THIS_IS_A_MACRO
    

    This kind of macros are used for conditional compilation.

  2. Symbolic constants. For example

    #define SOME_SYMBOLIC_CONSTANT  123
    

    These kind of macros are what you're thinking of.

  3. Function-like macros. Foe example

    #define SOME_MACRO(a_macro_argument)  printf("Macro invoked with argument %d\n", a_macro_argument)
    

    This kind of macro is used very much like functions, but are replaced by the preprocessor in the source code before the compiler parser sees the code, with the macro arguments replaced with their actual values.

Lets take the function-like macro and how it will be expanded by the preprocessor:

SOME_MACRO(123);

The above will be replaced like

printf("Macro invoked with argument %d\n", 123);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

Thus, in C++, never define getchar and putchar as member functions of a class. In case, they are defined as macros in stdio.h file, the compiler would throw all sorts of strange errors.

#include <stdio.h>

class My_IO_Device
{
    int putchar (int c); // seemingly innocent
};

I do not know whether <cstdio> guarantees them to be implemented as functions.

Krishnendu
  • 116
  • 4