6

There's this code that compiles with Windows SDK:

UINT cFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);

where DragQueryFileW() has this signature:

UINT DragQueryFileW(HDROP, UINT, LPWSTR, UINT );

and UINT is defined somewhere in SDK headers like this:

typedef unsigned int UINT;

for the platform where int is surely 32-bits. As usual, types like UINT are meant to have fixed width independent on the system bitness, so if the same code has to be recompiled on some other platform, where DragQueryFileW() is reimplemented somehow there will also be a corresponding typedef that will make UINT map onto a suitable 32-bit unsigned type.

Now there's a static analysis tool that looks at 0xFFFFFFFF constant and complains that it is an unportable magic number and one should use -1 instead. While of course -1 is good and portable I can't see how using the 0xFFFFFFFF constant could be a problem here since even when porting the type will still be 32-bit and the constant will be fine.

Is using 0xFFFFFFFF instead of -1 to set all bits safe and portable in this scenario?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    May be static analyzer complains, because it may not worry about 32-bit or 64-bit. – iammilind Jun 28 '11 at 06:12
  • Sounds like a false positive in the static analysis tool. It may not be able to see that you're always using that constant in a 32-bit context. – Cameron Skinner Jun 28 '11 at 06:13
  • @Jeremy Friesner: APIs are full of legacy names that have a fixed meaning. Take Microsofts `DWORD` as example, which means double word. AFAIK it stems from times where they were coding almost exclusively in 16-bit mode where a word is 16-bits, so a double-word is 32-bit. It still means 32-bits, although in 32-bit mode it's a word and in 64-bits is a half-word. – DarkDust Jun 28 '11 at 06:25
  • 1
    @ybungalobill: See [this answer](http://stackoverflow.com/questions/809227/is-it-safe-to-use-1-to-set-all-bits-to-true/809341#809341) to the question sharptooth has linked, it explains why using negation is not a good idea (although it seems like a natural solution). – DarkDust Jun 28 '11 at 06:27

4 Answers4

12

The portable way to fill all bits (regardless of type size) is really:

type variable = (type)-1;

as in:

UINT foo = (UINT)-1;

or more portable using C99 type names:

uint32_t foo = (uint32_t)-1;

The C standard guarantees that assigning -1 sets all bits.

Now, if you can guarantee that your variable is unsigned 32 bits then using 0xFFFFFFFF is alright as well, of course. But I'd still go for the -1 variant.

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • No, this works because the Standard makes it so. Even on a platform that doesn't use two's complement the implementation has to guarantee it works. – Luc Danton Jun 28 '11 at 06:44
  • @Luc Danton: You're right. Read that in the meantime as well and have now corrected it. – DarkDust Jun 28 '11 at 06:46
4

you could use:

type var =  0;
var = ~var;
mac
  • 42,153
  • 26
  • 121
  • 131
Chethan
  • 905
  • 1
  • 10
  • 18
3

One potential problem I see with 0xFFFFFFFF is that you can easily miss one F and initialize in a complete dummy value.

I believe that it is better to define a constant:

#define  ALL_ONES_32BIT ((UINT) -1)

and use that everywhere.

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
2

0xffffffff is for sure a reliable way to set all bits to one in 32 bits. but I wouldn't depend on a UINT always being 32 bits.

to make it less "magic" you could also write it: (1 << 32) - 1

jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
  • I'm not sure whether the shifting is a good idea. Using -1 works everywhere, as in theory, it is a endless stream of 1s in 2's complement. – DarkDust Jun 28 '11 at 06:18