"Bitwise And" and Left-Padding in C++
Asked Answered
A

4

5

I have a macro that looks something like this:

Foo(x) ((x - '!') & 070)

If I call the following code:

Foo('1') => 16

However, if I call the following code:

(('1' - '!') & 70) => 0

So my question is, what's going on here? Why does x & 070 compute to x but x & 70 compute to 0?

My guess is that the extra 0 on the left is forcing 60 to take 2 bytes instead of 1. In that case, wouldn't the bitwise & be as follows?

0000 0000 0001 0000     '16
0000 0000 0100 0110 &   '70
-------------------
0000 0000 0000 0000
Angrist answered 1/7, 2010 at 18:10 Comment(1)
I knew the answer to this (0 prefix = octal constant) but I can honestly say in more than 20 years of C programming, I've never seen it used. It's just one of those things that seems to have originated from a time when it would have been useful, maybe something to do with teletype machines or whatever. As an embedded guy, I'm always miffed that there's not something like a 'b' prefix for binary constants (yes, I have my own ways of doing this in C & C++, too bad it's not built into the language).Hertahertberg
M
12

In C++, a constant with a leading 0 is an octal constant, not a decimal constant. It is still an integer constant but 070 == 56.

This is the cause of the difference in behaviour.

Moxa answered 1/7, 2010 at 18:12 Comment(1)
Thanks, I expected it to be something straightforward, but didn't realize I was in the wrong base!Angrist
M
7

No, the extra 0 means the number is read as octal (base 8). That means it doesn't say 70, but 56:

0000 0000 0001 0000     '16 
0000 0000 0011 1000 &   '56
------------------- 
0000 0000 0001 0000 
Moreover answered 1/7, 2010 at 18:12 Comment(0)
C
3

Prepending the 070 with a 0 like you are doing tells the compiler to interpret it as octal, not decimal. You probably want to say 70.

Colyer answered 1/7, 2010 at 18:13 Comment(0)
B
3

As others said, 070 is an octal (and 0x70 a hexadecimal) constant, which is where your problem lies.

I'd like to add, though, that you should use inline functions instead of macros:

inline int Foo(int x) { return (x - '!' & 070); }

C++ has done a lot to allow us to get rid of the preprocessor for many things, because it's bad, misbehaving, and dangerous. If you can do without it, do so.
(And if you use it, at least have the mercy on those having to deal with your code later to make macros all-uppercase.)

Brogle answered 1/7, 2010 at 18:19 Comment(1)
The original code was actually written by someone else. I'm merely porting it to a different language.Angrist

© 2022 - 2024 — McMap. All rights reserved.