UInt64 Shift Left Behavior

I was experimenting with bitwise operations on UInt64 and observed some questionable behavior.

var word: UInt64 = 0xffffffff
print("\(String(format: "%016x", word))")
word <<= 1
print("\(String(format: "%016x", word))")

Here's the output from this code:

00000000ffffffff

00000000fffffffe

Is this a bug? Or is this the expected behavior? If so, why?

Cheers,
-Patrick

What is the function String(format:_:)?

Your format string is off; %x represents a C(Unsigned)Int, but that's only 32 bits. UInt64 is the same size as a CUnsignedLongLong, so %llx would be a better substitution.

2 Likes

Part of foundation.

I'm tinkering more and think I need a different format string to accommodate the 64-bit unsigned integer.

You beat me to it.

Thank you.

Note that instead of using formatters for this particular case, you can also use String(word, radix:16), which avoids the issues with argument size.

2 Likes

Heh, I was going to suggest this, but padding(toLength:withPad:startingAt:) is very verbose, and I'm not sure I want to recommend an API that isn't clear about whether it's using UTF-16 or Character offsets.

It also appears that padding(toLength:withPad:startingAt:) only does "right padding", if I am reading and trying it out correctly.

let s2 = String(99).padding(toLength: 5, withPad: "0", startingAt: 0)
print(s2)

Results:
99000

Is anyone working on some truly "Swifty" StringProtocol methods to perhaps replace those in Foundation? It seems to me that Foundation is:

  • Old
  • Based on Objective-C use cases and needs and not Swift's
  • Often just hard to work with

I believe it's also, by design, equivalent to size_t and ptrdiff_t on all supported platforms, so %zx and %tx should both work, if you want something less cumbersome than %llx.

Int is equivalent to ptrdiff_t, but UInt64 isn't.

Oh, my mistake. I thought I'd read UInt not UInt64. Carry on.

1 Like