difference inbetween macro & function

Discussion in 'C Programming' started by jason, Nov 6, 2007.

  1. jason

    jason Guest

    Hi,

    I learned my lesson about passing pointers, but now I have a question
    about macros.

    Why does the function work and the MACRO which is doing the same thing
    on the surface, does not work in the following small example ?

    #include <stdio.h>

    #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)

    double percent(double a, double b) {
    return ((a - b) / a) * 100.0;
    }

    int main(void) {

    printf("%g%%\n", percent(1000, 100));
    printf("%g%%\n", PERCENTAGE(1000, 100));

    return 0;
    }

    Thank you !

    jason
    jason, Nov 6, 2007
    #1
    1. Advertising

  2. jason

    gallows Guest

    On 6 Nov, 17:59, jason <> wrote:
    > Hi,
    >
    > I learned my lesson about passing pointers, but now I have a question
    > about macros.
    >
    > Why does the function work and the MACRO which is doing the same thing
    > on the surface, does not work in the following small example ?
    >
    > #include <stdio.h>
    >
    > #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)
    >
    > double percent(double a, double b) {
    > return ((a - b) / a) * 100.0;
    >
    > }
    >
    > int main(void) {
    >
    > printf("%g%%\n", percent(1000, 100));
    > printf("%g%%\n", PERCENTAGE(1000, 100));
    >
    > return 0;
    >
    > }
    >
    > Thank you !
    >
    > jason


    Well, that macro isn't the same as percent(). You have to cast to
    double, e.g.:

    #define PERCENTAGE(a, b) ( (a - b) / (double) a * 100 )
    gallows, Nov 6, 2007
    #2
    1. Advertising

  3. jason

    santosh Guest

    On Tuesday 06 Nov 2007 10:29 pm jason <> wrote in
    article <47309d6d$0$2540$4all.nl>:

    > Hi,
    >
    > I learned my lesson about passing pointers, but now I have a question
    > about macros.
    >
    > Why does the function work and the MACRO which is doing the same thing
    > on the surface, does not work in the following small example ?
    >
    > #include <stdio.h>
    >
    > #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)
    >
    > double percent(double a, double b) {
    > return ((a - b) / a) * 100.0;
    > }
    >
    > int main(void) {
    >
    > printf("%g%%\n", percent(1000, 100));
    > printf("%g%%\n", PERCENTAGE(1000, 100));
    >
    > return 0;
    > }
    >
    > Thank you !


    Macros have no concept of types because they are processed before the
    compiler proper begins. In your example the constants in the macro
    invocation are treated as integers causing the division by 'a' to be
    truncated to zero.

    Use a decimal point on the constants to force the compiler to treat them
    as double values.

    PERCENTAGE(1000.0, 100.0);
    santosh, Nov 6, 2007
    #3
  4. jason

    John Gordon Guest

    In <47309d6d$0$2540$4all.nl> jason <> writes:

    > Why does the function work and the MACRO which is doing the same thing
    > on the surface, does not work in the following small example ?


    > #include <stdio.h>


    > #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)


    > double percent(double a, double b) {
    > return ((a - b) / a) * 100.0;
    > }


    > int main(void) {


    > printf("%g%%\n", percent(1000, 100));
    > printf("%g%%\n", PERCENTAGE(1000, 100));


    > return 0;
    > }


    You're using 1000 and 100 instead of 1000.0 and 100.0 and therefore all
    of the calculations except for the final multiplication are done using
    integer math instead of floating-point math.

    Specifically, this part of the macro:

    ((a - b) / a)

    Will expand to this:

    ((1000 - 100) / 1000)

    Which further simplifies to this:

    900 / 1000

    And since these numbers are both integers, integer math is used, which
    produces a reult of zero.

    --
    John Gordon A is for Amy, who fell down the stairs
    B is for Basil, assaulted by bears
    -- Edward Gorey, "The Gashlycrumb Tinies"
    John Gordon, Nov 6, 2007
    #4
  5. jason

    jason Guest

    Re: difference inbetween macro & function, thnkx!

    On Tue, 06 Nov 2007 17:38:02 +0000, John Gordon wrote:
    > In <47309d6d$0$2540$4all.nl> jason
    > <> writes:
    >
    >> Why does the function work and the MACRO which is doing the same thing
    >> on the surface, does not work in the following small example ?

    >
    >> #include <stdio.h>

    >
    >> #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)

    >
    >> double percent(double a, double b) {
    >> return ((a - b) / a) * 100.0;
    >> }

    >
    >> int main(void) {

    >
    >> printf("%g%%\n", percent(1000, 100)); printf("%g%%\n",
    >> PERCENTAGE(1000, 100));

    >
    >> return 0;
    >> }

    >
    > You're using 1000 and 100 instead of 1000.0 and 100.0 and therefore all
    > of the calculations except for the final multiplication are done using
    > integer math instead of floating-point math.
    >
    > Specifically, this part of the macro:
    >
    > ((a - b) / a)
    >
    > Will expand to this:
    >
    > ((1000 - 100) / 1000)
    >
    > Which further simplifies to this:
    >
    > 900 / 1000
    >
    > And since these numbers are both integers, integer math is used, which
    > produces a reult of zero.


    Ah sounds logical indeed..

    Thank you all, for the answers & explanations.

    Jas.
    jason, Nov 6, 2007
    #5
  6. jason <> writes:
    > I learned my lesson about passing pointers, but now I have a question
    > about macros.
    >
    > Why does the function work and the MACRO which is doing the same thing
    > on the surface, does not work in the following small example ?
    >
    > #include <stdio.h>
    >
    > #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)
    >
    > double percent(double a, double b) {
    > return ((a - b) / a) * 100.0;
    > }
    >
    > int main(void) {
    >
    > printf("%g%%\n", percent(1000, 100));
    > printf("%g%%\n", PERCENTAGE(1000, 100));
    >
    > return 0;
    > }


    Others have explained why your macro doesn't work. I'll offer some
    additional advice.

    You get 100 points (on a scale of 0 to whatever the heck) for posting
    a complete program that exhibits the problem, but you lose 20 points
    for merely telling us that it "does not work" without explaining *how*
    it doesn't work. In this case, it was easy enough to figure out the
    problem, but in general you should tell us *how* it didn't work --
    i.e., what output you expected, what output you got, and perhaps why
    you think your expected output is right and what you got is wrong.

    A good resource for this kind of thing is
    <http:°www.catb.org/~esr/faqs/smart-questions.html>.

    As for your macro, leaving aside the type problem, I see two other
    potential issues. First, it always evaluates the first argument
    twice. This isn't necessarily a problem; the all-caps name warns
    users that this is a macro, and this kind of thing might happen.

    Second, for a function-like macro that expands to an expression, you
    should always fully parenthesize the entire expression (which you did)
    *and* each occurrence of an argument (which you didn't). Specifically:

    #define PERCENTAGE(a, b) ((((a) - (b)) /(a)) * 100.0)

    (Note: it's not *always* strictly necessary, but I find it much easier
    to be consistent than to remember the cases where it isn't.)

    This doesn't matter if the arguments are simple identifiers or
    constants, but imagine what happens if the arguments are more complex
    subexpressions. Macro expansion knows nothing about operator
    precedence; it just blindly expands each argument in place. Here's an
    example of how failing to parenthesize sufficiently:

    #include <stdio.h>

    #define SIX 1+5
    #define NINE 8+1

    int main(void)
    {
    printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
    return 0;
    }

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 6, 2007
    #6
  7. Re: difference inbetween macro & function, thnkx!

    "jason" <> a écrit dans le message de news:
    4730adc8$0$2540$4all.nl...
    > On Tue, 06 Nov 2007 17:38:02 +0000, John Gordon wrote:
    >> In <47309d6d$0$2540$4all.nl> jason
    >> <> writes:
    >>
    >>> Why does the function work and the MACRO which is doing the same thing
    >>> on the surface, does not work in the following small example ?

    >>
    >>> #include <stdio.h>

    >>
    >>> #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)

    >>
    >>> double percent(double a, double b) {
    >>> return ((a - b) / a) * 100.0;
    >>> }

    >>
    >>> int main(void) {

    >>
    >>> printf("%g%%\n", percent(1000, 100)); printf("%g%%\n",
    >>> PERCENTAGE(1000, 100));

    >>
    >>> return 0;
    >>> }

    >>
    >> You're using 1000 and 100 instead of 1000.0 and 100.0 and therefore all
    >> of the calculations except for the final multiplication are done using
    >> integer math instead of floating-point math.
    >>
    >> Specifically, this part of the macro:
    >>
    >> ((a - b) / a)
    >>
    >> Will expand to this:
    >>
    >> ((1000 - 100) / 1000)
    >>
    >> Which further simplifies to this:
    >>
    >> 900 / 1000
    >>
    >> And since these numbers are both integers, integer math is used, which
    >> produces a reult of zero.

    >
    > Ah sounds logical indeed..


    It should also be noted that macro arguments must be parenthesized in the
    expansion to prevent operator precedence problems:

    Your definition of PERCENTAGE will not work as expected some of the
    arguments are expressions:
    #define PERCENTAGE(a, b) (((a - b) / a) * 100.0)

    PERCENTAGE(1 + 2, 3) will expand as

    (((1 + 2 - 3) / 1 + 2) * 100.0) which evaluates to 200.0 instead of the
    expected 0.0

    The fix is easy:
    #define PERCENTAGE(a, b) ((((a) - (b)) / (a)) * 100.0)

    Also note that the initial part of the computation will be done with integer
    arithmetics if both a and b are integers.
    A simple fix for this is:
    #define PERCENTAGE(a, b) ((((double)(a) - (b)) / (a)) * 100.0)

    The expression can actually be simplified a bit because / and * are left
    associative, so ``(a / b) * c'' is the same is ``a / b * c'' and the left
    operand of * is already a double so 100 can be used instead of 100.0.
    #define PERCENTAGE(a, b) (((double)(a) - (b)) / (a) * 100)

    Finally, you notice that a is evaluated twice in the expansion of the macro.
    Invoking this macro with an expression with side effects as a first argument
    will not perform as expected, and may even invoke undefined behaviour:

    PERCENTAGE(compute_total_and reset(), 100) will invoke the function
    compute_total_and_reset twice.

    The only way to fix this is to use a function instead of a macro. In c99,
    this function can be declared ``inline'' as a hint for the compiler to
    generate code without a function call, but this is an optimisation you
    should not be concerned with at this stage.

    So remember this:
    1- use functions, not macros.
    2- if you break rule 1, always parenthesize the macro arguments in the
    expansion
    3- if you break rule 1, be careful about multiple evaluation, use capitals
    for the macro name to make them obvious.
    4- if you break rule 1, macros are untyped, be careful how the expansion
    will evaluate depending on the types of the arguments.
    5- don't break rule 1

    --
    Chqrlie.
    Charlie Gordon, Nov 8, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Girish
    Replies:
    3
    Views:
    404
    Girish
    Feb 24, 2004
  2. Mike Miller
    Replies:
    1
    Views:
    386
    Murat G.
    Oct 19, 2003
  3. Newbie_sw2003

    What is the difference between MACRO and FUNCTION?

    Newbie_sw2003, Sep 10, 2003, in forum: C Programming
    Replies:
    7
    Views:
    19,978
    Ed Morton
    Sep 11, 2003
  4. Patrick Kowalzick
    Replies:
    5
    Views:
    458
    Patrick Kowalzick
    Mar 14, 2006
  5. Replies:
    54
    Views:
    451
    Michele Dondi
    Jan 16, 2005
Loading...

Share This Page