The size of int and uint

2,191 views
Skip to first unread message

snilsson

unread,
Jan 13, 2011, 12:11:13 PM1/13/11
to golang-dev
A few questions about this code:

// Integer limit values.
const (
MaxUint = ^uint(0) // 1<<32 - 1 or 1<<64 - 1
MaxInt = int(MaxUint >> 1) // 1<<31 - 1 or 1<<63 - 1
MinInt = int(-MaxInt - 1) // -(1<<31) or -(1<<63)
BitsPerWord = int(32 * (1 + MaxUint>>63)) // 32 or 64
)

Do these belong in the math package with the other integer limit
values?

Should they really be constants? They change between platforms.

Is is possible to declare them as untyped constants? If so, how do you
do it?

Is the word length guaranteed to be the same for int and uint?

Russ Cox

unread,
Jan 13, 2011, 1:04:31 PM1/13/11
to snilsson, golang-dev
> // Integer limit values.
> const (
>        MaxUint     = ^uint(0)                    // 1<<32 - 1 or 1<<64 - 1
>        MaxInt      = int(MaxUint >> 1)           // 1<<31 - 1 or 1<<63 - 1
>        MinInt      = int(-MaxInt - 1)            // -(1<<31) or -(1<<63)
>        BitsPerWord = int(32 * (1 + MaxUint>>63)) // 32 or 64
> )
>
> Do these belong in the math package with the other integer limit
> values?

I don't think so. If you care about what max and min are,
you should be using an explicitly sized type.

> Should they really be constants? They change between platforms.

So does syscall.OS.

> Is is possible to declare them as untyped constants? If so, how do you
> do it?

Sure. const MaxUint = 1<<32 - 1 or const MaxUint = 1<<64 - 1
would be the cleanest way.

There are "portable" but less readable ways too.
http://golang.org/src/pkg/big/arith.go

> Is the word length guaranteed to be the same for int and uint?

It looks like that is missing from the spec, but the answer is yes.

Russ

snilsson

unread,
Jan 13, 2011, 2:20:10 PM1/13/11
to golang-dev
> > Is is possible to declare them as untyped constants? If so, how do you
> > do it?
>
> Sure.  const MaxUint = 1<<32 - 1 or const MaxUint = 1<<64 - 1
> would be the cleanest way.

That is assuming that you know the answer. What if you want to write
cross-platform code?

>
> There are "portable" but less readable ways too.http://golang.org/src/pkg/big/arith.go

Yes, I'm familiar with those tricks, but they don't give typeless
constants. ^uint(0) has
type uint and this propagates when you use it in constant expressions.

>
> > Is the word length guaranteed to be the same for int and uint?
>
> It looks like that is missing from the spec, but the answer is yes.

Good, that's what I hoped for.

Russ Cox

unread,
Jan 13, 2011, 2:38:32 PM1/13/11
to snilsson, golang-dev
>> There are "portable" but less readable ways too.http://golang.org/src/pkg/big/arith.go
>
> Yes, I'm familiar with those tricks, but they don't give typeless
> constants. ^uint(0) has
> type uint and this propagates when you use it in constant expressions.

Not when it is on the right hand side of a shift.
In the example I pointed at only _m and _logS have types.

Russ

snilsson

unread,
Jan 13, 2011, 3:30:54 PM1/13/11
to golang-dev
Great, that solved my problem. Thanks!

Nigel Tao

unread,
Jan 13, 2011, 5:31:35 PM1/13/11
to r...@golang.org, snilsson, golang-dev
On 14 January 2011 05:04, Russ Cox <r...@golang.org> wrote:
> I don't think so.  If you care about what max and min are,
> you should be using an explicitly sized type.

A possible counter-example is when you want to rotate an int, or
zigzag-encode an int as a uint, but you don't care whether it's a
32-bit or 64-bit int.

The zigzag encoding for 32-bit ints is: uint((i << 1) ^ (i >> 31)). It
maps [0, -1, 1, -2, 2, ...] to [0, 1, 2, 3, 4, ...]. Sure, you can
implement it with an if statement, but it might be faster as pure
bitwise operations.

David Symonds

unread,
Jan 13, 2011, 6:08:10 PM1/13/11
to Nigel Tao, r...@golang.org, snilsson, golang-dev

That hardly ever comes up. I've only seen ZigZag encoding as applied
to protocol buffers, and you only ever deal with explicit int32/int64
types there (or their unsigned variants).


Dave.

Nigel Tao

unread,
Jan 13, 2011, 6:56:58 PM1/13/11
to David Symonds, r...@golang.org, snilsson, golang-dev
On 14 January 2011 10:08, David Symonds <dsym...@golang.org> wrote:
> That hardly ever comes up. I've only seen ZigZag encoding as applied
> to protocol buffers, and you only ever deal with explicit int32/int64
> types there (or their unsigned variants).

I haven't needed it myself, but you might want to zigzag encode an int
(not an int32) if you want to use the resultant value as a slice index
(i.e. map from signed ints near zero to something). Sure, you could
convert to int64, do zigzag64, and convert back to int, but on a
32-bit processor it'd be faster to just do zigzag. Alternatively (for
the map of signed ints example), you could just add an index bias, but
then you have a lower bound on the possible indices, or you have to
manage changing the bias.

Similarly, I could imagine hashing a stream of ints as "hash =
rotateLeft(hash, 5) ^ i", and the rotateLeft implementation depends on
sizeof(int). It's not a great hash, but it's quick and simple.

I'm not saying that these use cases are common, I'm just suggesting
use cases for a IntBits constant.

Nigel Tao

unread,
Jan 13, 2011, 7:07:34 PM1/13/11
to David Symonds, r...@golang.org, snilsson, golang-dev
On 14 January 2011 10:56, Nigel Tao <nigel.t...@gmail.com> wrote:
> I'm not saying that these use cases are common, I'm just suggesting
> use cases for a IntBits constant.

Another use case for MinInt (as opposed to MinInt32) is if you want to write:

func max(a []int) int {
var x int = math.MinInt
for _, y := range a {
if x < y {
x = y
}
}
return x
}

Reply all
Reply to author
Forward
0 new messages