Weird compiler error message on correct statement

I have this line in my code:

SensorMessage.smtype = (TAL | WARN);

which, I believe, is correct. Yet the compiler tells me:

suggest parentheses around arithmetic in operand of '|' [-Werror=parentheses]

Hmmm. I think:

  • the statement is correct and free of doubts even without parenthesis
  • now that I do have parenthesis what more can I do?
  • and why does a suggestion result in a failure of compilation?

Where is the fault?

why does a suggestion result in a failure of compilation?

Please copy the full text of the message using the "Copy error messages" button in the IDE and your full sketch so that others can compile it

That is not an error, it is a warning.

Show us how TAL and WARN are defined. The problem is in one of those definitions.

Since the two are upper case, I expect that they are #defined somewhere and aren't as simple as they appear in your snippet. Try putting each of them in parens too.

TAL and WARN are indeed #defines, and rather simple ones:

    #define TERM            1
    #define AL              4               // print to Terminal and ActionLog
    #define WARN            64              // NVS storage
    #define TAL             TERM + AL       // print to Terminal and ActionLog

I'm afraid I can't post the full code, as it is not only proprietary, but also close to 1 MB.

The compilation ends with these two lines:

exit status 1
suggest parentheses around arithmetic in operand of '|' [-Werror=parentheses]

and in between I read:

cc1plus: some warnings being treated as errors

it is diffuse enough to not be conclusive, but it looks like this "suggest" might be taken as error.

But this suggestion should not be there in the first place. I think.

As suspected. The compiler thinks you want to or TAL and WARN together. Operator precedence means that you will, but it's warning you that since it did a macro expansion for you, you might want to add brackets to make your intent clearer.

Better to put the brackets in the #define itself in case you've got the same thing elsewhere.

I changed to this:

 #define TAL             (TERM + AL)       // print to Terminal and ActionLog

and the "suggestion" is gone!

But what you say the compiler is thinking is exactly what I want: TAL = TERM + AL = 1 + 4 = 5. And TAL | WARN would compare with 69. Or not? Where am I wrong?

OK, now I understand (I believe). Using the #defines makes my statement:

SensorMessage.smtype = (TAL | WARN);

to:
SensorMessage.smtype = (TERM + AL | WARN)
and that could indeed be misleading. As wildbill pointed out it would be correct anyway, but only in this case. Many thanks!

TERM + AL +  | WARN);

It's just a warning, but apparently your setup treats warnings as errors.

It's just trying to tell you that a macro was expanded on this line and that it may not be doing exactly what you expected. In this case, it is doing just what you wanted, but in another situation that might not be true and the compiler can't read your mind.

ullix:
I changed to this:

 #define TAL             (TERM + AL)       // print to Terminal and ActionLog

and the "suggestion" is gone!

But what you say the compiler is thinking is exactly what I want: TAL = TERM + AL = 1 + 4 = 5. And TAL | WARN would compare with 69. Or not? Where am I wrong?

What the compiler actually "sees" is this:

#define TERM           1
#define AL               4               // print to Terminal and ActionLog
#define WARN          64              // NVS storage
#define TAL             TERM + AL       // print to Terminal and ActionLog
SensorMessage.smtype = (1 + 4  | 64);

In this case, the result will be correct without the parens o nthe definition of TAL, but that will not always be true for other values of the variables, or other expressions.

Bottom line, when creating #defines that contain expressions with ANY operators, the expression in the #define should be fully parenthesized, even if the expression itself does not require it. You have NO idea how that #define will later be used, and in many cases using the #define in another expression can cause evaluation of the #define to occur in the wrong order. Always putting in the parens ENSURES the #define will be evaluated as intended.

Advice taken, Thanks!

Here's a trivial example:

#define X 3 + 4

int y = X * 10;

What is the value of y?

You would likely expect y to be 70, but it will actually be 43.

The compiler will see:

#define X 3 + 4
int y = 3 + 4 * 10;

Since multiplication takes precedence over addition, 4 is multiplied by 10, and 3 is added to that, giving y the value 43.

The following will correctly give y the value 70:

#define X (3 + 4)

int y = X * 10;

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.