-1

A topic has the following code, which is required to indicate the location of the error.

#include<iostream>
#define PT 3.5;
#define S(x) PT*x*x
    
void main() {
    int a = 1, b = 2;
    std::cout << S(a + b);
}

I think ";" caused this problem ,and deleted ';' the post compilation test can get the correct results.But the teacher thinks that variables cannot be used in macro definition. I'm not sure who is right.

I've seen a lot of answers, but what I want to know is not whether it's reasonable to write like this, but what causes the program error in the end.

Add ';' after '#define' Not particularly good, but the compilation can pass. "#define" can also allow variables to appear. So the final error reason is "* a + b"?

jerx
  • 77
  • 4
  • Location of which error? (Both macros are flawed.) – JaMiT Dec 10 '21 at 04:02
  • 1
    `S(a + b)` -> `PT * a + b * a + b` - is not what you probably want. – 273K Dec 10 '21 at 04:02
  • 3
    "*the teacher thinks that variables cannot be used in macro definition*" - if your teacher can't see the problems with these macros, you need a better teacher. – Remy Lebeau Dec 10 '21 at 07:05
  • 1
    As pointed out by Bathsheba elsewhere, the signature of `main` is not valid C++. Please see [What should main() return?](https://stackoverflow.com/q/204476/1553090) – paddy Dec 10 '21 at 10:20
  • "Can ";" be added **after** `#define` ? " - Not really. It's _part of_ the #define line. – MSalters Dec 10 '21 at 13:21

3 Answers3

2

There's a couple of problems. Yes, the PT will expand to 3.5; and cause a syntax error. Change that to:

#define PT 3.5

The other issue is that S(a + b) will expand to PT*a + b*a + b which is clearly not what you want. As a matter of convention, macros that perform arithmetic should wrap any expandable parts in parentheses, and the entire macro should also be in parentheses:

#define S(x) ((PT)*(x)*(x))

This ensures that you don't have to worry about expanded expressions wreaking havoc due to operator precedence rules.

Regarding the comment about your teacher...

the teacher thinks that variables cannot be used in macro definition

It's possible that they are talking about the fact that x is just a placeholder for expansion. If you pass a + b and use x twice, then a + b will be evaluated twice. Imagine if you called S(++a)... You'd get PT*(++a)*(++a)

It's usually more appropriate to just write a function, and that avoids problems like the above.

double S(int x) {
    return PT * x * x;
}

Or even:

template<class T>
double S(T x) {
    return PT * x * x;
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Please also mention `void main()` too as you're clearly aiming for completeness. – Bathsheba Dec 10 '21 at 09:51
  • That seems off-topic for a question about macros and would be better off as a comment on the original question. I hadn't noticed the issue at the time, but good spotting and I'll leave a comment there for you. – paddy Dec 10 '21 at 10:18
0

You can't put a semicolon after PT because your macro S(X) PT*x*x would get processed to 3.5;*x*x

Your S(x) macro is breaking because the semicolons breaks it into 2 statements. First is 3.5; and the second one is *x*x hence why you get the error.

To make it work you simply need to remove the ; in your definition of PT

0xd34dc0de
  • 493
  • 4
  • 10
0

Macros are just text substitution, so you can do pretty much anything you want, as long as the result of the substitution is valid code. So the literal answer to "Can ';' be added after #define" is yes, but the result might not work.

#define calc(x) ((x) * (x));

void f() {
    int g = 3;
    int h = calc(g);
}

The result of the macro expansion is

int h = ((g) * (g));;

That's valid code; the second semicolon marks the end of an empty expression, just as if it had been written

int h = ((g) * (g));
;

That's bad style, of course, and it could cause problems in other contexts, so the "right" way to use that macro would be

    int h = calc(g)

That way, the text that results from the macro expansion would only have one semi-colon. But that looks weird, and the macro really shouldn't have that semicolon in it.

As to using variables, again, it depends on what the result of the text substitution is.

#define calc (x) * (x)

void f() {
    int x = 3;
    int y = calc;
}

That's okay; the code is equivalent to

void f() {
    int x = 3;
    int y = (x) * (x);
}

On the other hand, this isn't okay:

void f() {
    int b = 3;
    int y = calc;
}

It doesn't work because there is no x there. So this macro has vary limited usefulness; there are rare situations where it might be appropriate, but, in general, it's a bad idea.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165