R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215327

Alternative to (unsigned long long) cast without warnings

I have a macro that needs to be able to accept arbitrary integer or pointer types and convert them to unsigned long long. The natural way to do this is just to cast, and that works, but with the default GCC warnings it yields "cast from pointer to integer of different size", and I'd like to avoid that. The natural way to avoid the warning is with an intermediate cast, as in (unsigned long long)(uintptr_t)x, but that doesn't work in my case because:

  1. It will truncate integer inputs that don't fit in uintptr_t.
  2. It will break proper conversion of signed inputs, e.g. -1 may become 0xffffffff instead of 0xffffffffffffffff.

If I had an expression (perhaps making fancy use of the ?: operator) that could distinguish pointer from integer types, I could break it down into the two cases and apply the (uintptr_t) cast first for pointer inputs but not for integer ones. Any ideas on a trick that would work?

Upvotes: 1

Views: 982

Answers (1)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215327

This seems like it should work:

sizeof (1?(x):(unsigned long long)0) < sizeof (unsigned long long)
    ? (uintptr_t)(x)
    : (unsigned long long)(x)

Cases:

  1. x has any integer type. Then 1?(x):(unsigned long long)0 has type unsigned long long and thus the second branch is taken, converting directly to unsigned long long.
  2. x has pointer type and the pointer type is smaller than unsigned long long. Then 1?(x):(unsigned long long)0 has the original pointer type and the first branch is taken, going through uintptr_t.
  3. x has pointer type and the pointer type is the same size (or larger, but I'll assume that doesn't happen) as unsigned long long. Then the second branch is taken, but there's no warning to be issued anyway.

I'm not clear if GCC can avoid issuing a warning for dead code (the branch that won't be taken), but if not, perhaps __builtin_choose_expr is a solution.

Upvotes: 1

Related Questions