-2

This is one of the weirdest things I've encountered. My problem is this:

First of all, I'm using Visual Studio 2015 on Windows 7. In a C++\CLI project, I have code similar tho the following:

void Class::function(int flag) 
{
   if ((flag & CONST) != 0)
       printf("Passed.");
   else 
       printf("Failed.");
}

Where CONST is defined in another (Non-CLR) DLL to be 0x111. Looks pretty straight-forward. The problem I've had is that when I entered the procedure where flag is equal to 0x40. To me, it looks as if this procedure should print Failed., when in fact it it printed Passed.. The next thing I did, was to alter my code to the following:

void Class::function(int flag) 
{
   int local = CONST, localRes = flag & local, res;
   if ((res = (flag & CONST)) != 0)
       printf("Passed.");
   else 
       printf("Failed.");
}

Now, breaking the execution on printf, I got the following values in the Watch:

res = 0x110
local = 0x111
localRes = 0x0

I could not watch the value of CONST though VS didn't didn't know it in that context.

As far as I'm concerned, I could get around this by using local, but I'd rather understand it. Could someone please tell me what's wrong with the compilation/execution? Thanks!

EDIT: In the included header file (included as extern "C"), it is defined as so:

#define CONST /
   C1 | C2 | C3

Where quite regularly, C1 is 0x1, C2 is 0x10, and C3 is 0x100.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
EZLearner
  • 1,614
  • 16
  • 25
  • 1
    How is `CONST` DEFINED? – Thomas Matthews Nov 24 '16 at 22:06
  • Have you tried defining `CONST` as `extern`? – Thomas Matthews Nov 24 '16 at 22:08
  • Maybe this is not so clear. Particularly the claim "defined in another non-CLR dll" seems quite unlikely, exporting data from a dll isn't very obvious. – Hans Passant Nov 24 '16 at 22:08
  • Without any extra information, I expect @ThomasMatthews is onto something. For example. if `CONST` is a poorly-defined macro, you may have a change in behaviour when you use `flag & CONST` versus `flag & (CONST)`. – paddy Nov 24 '16 at 22:12
  • CONST could also be a class overridgin the biwise or operator... – jpo38 Nov 24 '16 at 22:14
  • @jpo38: Not in this case. For that to be an option, it would have to be on the left-hand side of the operator. – IInspectable Nov 24 '16 at 22:16
  • @jpo38 I think you mean the bitwise _and_ operator (not _or_). – paddy Nov 24 '16 at 22:17
  • @ThomasMatthews I updated my question – EZLearner Nov 24 '16 at 22:19
  • 1
    And there we have it. Case closed. – paddy Nov 24 '16 at 22:20
  • In case you missed @paddy's point, the problem is in the definition of the macro. Make it `#define CONST (C1 | C2 | c3)`. The parentheses are crucial. – Pete Becker Nov 24 '16 at 22:25
  • @IInspectable: if `CONST` is an instance of `STUPID` class class, one guy could have defined `int operator&( int a, const STUPID& b) { return 1; }`....and `operator int() { return 0x111; }` would have been funny... – jpo38 Nov 24 '16 at 22:25
  • @paddy: Yes, that's what I meant to write! – jpo38 Nov 24 '16 at 22:26
  • @jpo38: That's not a class overriding the operator. That's a free function. – IInspectable Nov 24 '16 at 22:27
  • @PeteBecker I wouldn't change a header file from an external API – EZLearner Nov 24 '16 at 22:27
  • @IInspectable: Agree. – jpo38 Nov 24 '16 at 22:27
  • Then you'll have to put parentheses around every use of `CONST`, because what you now refer to as "an external API" has a serious bug. – Pete Becker Nov 24 '16 at 22:28
  • *"included as `extern "C"`"* - I have no idea what that is supposed to mean. – IInspectable Nov 24 '16 at 22:28
  • @PeteBecker Very well, I'll try that. Also, I've already found a lot more serious bugs and inconsistencies in that company's APIs, so that wouldn't surprise me. Thanks. – EZLearner Nov 24 '16 at 22:31
  • @IInspectable http://stackoverflow.com/questions/67894/why-do-we-need-extern-c-include-foo-h-in-c – EZLearner Nov 24 '16 at 22:34
  • Further, this demonstrates why you should provide code that actually shows the problem when it's compiled. In the process of creating that code you probably would have uncovered the problem yourself. – Pete Becker Nov 24 '16 at 22:36
  • I didn't know the origin of the problem, or I wouldn't have asked here, so when asked for that code, I provided it. I am a veteran C# programmer, but new to C++, and I recently encountered the ugliest compilation bugs, so I thought this problem might've had something to do with VS or Windows. – EZLearner Nov 24 '16 at 22:42

1 Answers1

0

flag & CONST expands to flag & C1 | C2 | C3, equivalent to (flag & C1) | C2 | C3.

Don't ever #define expressions without parentheses, or operator precedence will bite you.

If you don't have control over the header, either wrap it in your own macro:

#define GOOD_CONST (CONST)

Or put it in a variable (use extern if needed to be exposed in a header):

unsigned int GOOD_CONST = CONST;

And use only that in your code.

Tomek Sowiński
  • 863
  • 5
  • 16