2
#include <stdio.h>
// 2.1
#define subm(a,b) (a - b)
#define cubem(a) (a * a * a)
#define minm minf
#define oddm oddf
//---------------------------Given Code------------------------------------
int subf(int a, int b) {
    return a - b;
}
int cubef(int a) {
    return a * a * a;
}
int minf(int a, int b) {
    if (a <= b) {
        return a;
    } else {
        return b;
    }
}
int oddf(int a) {
     if (a % 2 == 0) {
        return 0;
    } else {
        return 1;
    }
}
//----------------------------Given Code----------------------------------
// 2.2
int main() {
    int a = 5;
    int b = 7;

    subf(a,b);printf("subf = %d\n", subf(a,b));
    subm(a,b);printf("subm = %d\n", subm(a,b));
    subf(a++,b--);printf("subf = %d\n", subf(a++,b--));
    subm(a++,b--);printf("subm = %d\n", subm(a++,b--));

    cubef(a);printf("cubef = %d\n", cubef(a));
    cubem(a);printf("cubem = %d\n", cubem(a));
    cubef(--a);printf("cubef = %d\n", cubef(--a));
    cubem(--a);printf("cubem = %d\n", cubem(--a));

    minf(a,b);printf("minf = %d\n", minf(a,b));
    minm(a,b);printf("minm = %d\n", minm(a,b));
    minf(--a,--b);printf("minf = %d\n", minf(--a,--b));
    minm(--a,--b);printf("minm = %d\n", minm(--a,--b));

    oddf(a);printf("oddf = %d\n", oddf(a));
    oddm(a);printf("oddm = %d\n", oddm(a));
    oddf(a++);printf("oddf = %d\n", oddf(a++));
    oddm(a++);printf("oddm = %d\n", oddm(a++));
}

I'm having some trouble with putting the functions inside the macro. My professor wants us to understand how macro and functions are processed. The way I'm doing it is basically as you see here, but it's not working correctly, or at least

#define cubem(a) (a * a * a)

Is generating an error and I don't know why. Can someone please help?

edit: the error is as shown

hw02q2.c:42:31: warning: multiple unsequenced modifications to 'a'
      [-Wunsequenced]
        printf("cubem = %d\n", cubem(--a));
                                 ^~
hw02q2.c:4:19: note: expanded from macro 'cubem'
#define cubem(a) (a * a * a)
chqrlie
  • 131,814
  • 10
  • 121
  • 189
pepperguy3
  • 51
  • 2
  • 8
  • 2
    "generating an error and I don't know why". Please show the exact error you are getting so that we can more easily tell you why. – kaylum Jan 29 '17 at 10:03
  • It's updated with the error. – pepperguy3 Jan 29 '17 at 10:06
  • 1
    I don't see an error, only warnings – Karsten Koop Jan 29 '17 at 10:08
  • Nothing to do with the macro per se. You'd get the same without using macros (try it if you like). See [Why are these constructs using ++ undefined behavior?](http://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) – kaylum Jan 29 '17 at 10:09
  • It's not a problem with the macro, it's a problem with how you use it. Don't use pre/post-increment/decrement inside a single statement. – Sami Kuhmonen Jan 29 '17 at 10:09
  • It was noted that it is required to use both pre/increment/decrement so that when we print the values, we should expect different result due to how macro is processed differently than functions. How would I go about writing the statement that would correct the problem? – pepperguy3 Jan 29 '17 at 10:16
  • What does "put a function inside a macro" mean in the context of this question? You do not appear to be doing any such thing (whatever it may mean). – Clifford Jan 29 '17 at 12:30
  • I apologize for the informal usage of words and such but it was the best way that I could describe it. Basically, in the line of "#define minm minf", minf is a defined function in my code and to me, it looks like I'm putting the function, minf, into the macro, minm. I hope that was a bit more understanding. If there is a more correct terminology, please let me know. – pepperguy3 Jan 30 '17 at 21:01

3 Answers3

4

The reason is that

#define cubem(a) (a * a * a)

/* and later using it .... */

printf("cubem = %d\n", cubem(--a));

does text substitution, and produces

printf("cubem = %d\n", (--a * --a * --a));

which modifies a three times in one statement. That is undefined behaviour according to the C standard.

In comparison,

int cubef(int a) {
    return a * a * a;
}

/* and later */

printf("cubef = %d\n", cubef(--a));

evaluates --a once, passes the resultant value to cubef().

If you really want to "put a function in a macro", then do something like

#define cubem(a) cubef(a)

which causes the statement

printf("cubem = %d\n", cubem(--a));

to become

printf("cubem = %d\n", cubef(--a));

The problem with this is that it does not work with a macro that uses its argument more than once. For example

int sq(int a) {return a * a;}

#define cubesq(a) (a * sq(a))    /*  uses a more than once

causes

printf("cubesq = %d\n", cubesq(--a));

to be seen by the compiler as

printf("cubem = %d\n", (--a * cubesq(--a));

which, again, modifies a more once and causes undefined behaviour.

The reason is simple: the preprocessor does TEXT SUBSTITUTION and modifies source code seen by a later phase of the compiler.

Instead of "trying to put a function inside a macro", simply don't use macros. Write functions. Use functions. Or use macros, but respect their limitations (i.e. they don't work like functions do, even if they look like functions).

Peter
  • 35,646
  • 4
  • 32
  • 74
1

C Macros perform textual substitution: each instance is replaced with the macro definition with the macro parameter names replaced with the exact text of the instance arguments.

Your cubem macro defined as #define cubem(a) (a * a * a) will expand this way:

cubem(--a) -> (--a * --a * --a)

Modifying a multiple times within the same expression has undefined behavior. You cannot work around this problem portably. You could try using compiler extensions if you are familiar enough and don't mind relying on non-portable constructions.

The correct way to implement the function and have it expand inline is via an inline function definition:

static inline cubem(int a) { return a * a * a; }

Note also that the macro has other problems:

cubem(1 + 1) expands to (1 + 1 * 1 + 1 * 1 + 1) which evaluates to 4 instead of 8.

To avoid this problem, all macro arguments should be parenthesized:

#define cubem(a)  ((a) * (a) * (a))

But this definition still does not support arguments with side effects:

cubem(getchar()) will read 3 bytes from standard input.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

Since you invoke cubem(--a) like this, your cubem definition should avoid side effect.

#define cubem(a) \
({ \
    typeof(a) dummy_a = (a); \
    dummy_a * dummy_a * dummy_a; \
})

Above is a gcc c extension, read the gcc document, chapter

Statements and Declarations in Expressions

jacob
  • 671
  • 6
  • 15
  • 1
    `typeof` is not standard C. It is a compiler specific extension. And wrapping things in `({`/`})` does not allow a macro to give a value of `dummy_a * dummy_a * dummy_a` in standard C either. – Peter Jan 29 '17 at 10:19
  • When I replace my code with yours, it works, but I'm not understanding why it works or why 'dummy_a' or 'typeof(a)' is used. Can you explain more? – pepperguy3 Jan 29 '17 at 10:20
  • 2
    Nice try, but the above macro will fail if invoked as `cubem(dummy_a)`. This kind of exercice is interesting for pedagogical purposes, but the conclusion should be to write inline functions. – chqrlie Jan 29 '17 at 10:30