Goのintとint64の違いは何ですか?


86

(ファイルから読み取られた)整数を含む文字列があります。

私が変換しようとしているstringint使用しますstrconv.ParseInt()ParseIntビットサイズを指定する必要があります(ビットサイズ0、8、16、32、および64はint、int8、int16、int32、およびint64に対応します)。

ファイルから読み取られる整数は小さいです(つまり、通常のintに収まるはずです)。ただし、ビットサイズ0を渡すと、型の結果が得られますint64(おそらく、64ビットOSで実行しているためです)。

なんでこんなことが起こっているの?通常のintを取得するにはどうすればよいですか?(誰かがいつ、なぜ異なるint型を使用すべきかについての簡単な入門書を持っているなら、それは素晴らしいでしょう!)

編集:を使用してint64を通常のintに変換できint([i64_var])ます。しかしParseInt()、ビットサイズ0を要求しているときに、なぜint64が返されるのかはまだわかりません。


2
簡潔にするためにAtoiを使用しますか?また、ParseInt関数はエラーを返しますか?
マット

2
さて、今私は少し混乱しています。Atoi()を使用すると、intが得られ、すべてが機能します。私はparseInt(s, 0, 0)、base10を推測する必要があるを呼び出していました(文字列にはベースプレフィックスがないため)。ただし、AtoiはparseInt10のベースで呼び出すことの省略形です。ベースパラメータが返されるタイプに違いをもたらすのはなぜですか?
Isaac Dontje Lindell 2014

基本パラメーターは、入力文字列の読み取り方法を決定します。文字列は、「123」、「0xBEEFCAKE」、「1011101」、「0677」のようになります。これらはすべて異なる意味を持ち、異なる数値を生成します。の基本値0は、コードがそれ自体でこれを理解しようとすることを意味します。しかし、これが不可能な場合もあります。11(10進数)と11(2進数)はまったく異なる値を表します。
jimt 2014年

1
さて、私が本当に混乱しているのはドキュメントだと思います。Atoiのドキュメントには、これは単なる「の省略形」であるとだけ書かれていparseInt(s, 10, 0)ます。しかし、なぜatoiはint64intparseInt返すのに戻るのでしょうか?
Isaac Dontje Lindell 2014

1
正確になぜ、私はそれを前提とします知らないAtoi:CのAPIに精通している人たちに対応するために、単純に追加されましたint atoi ( const char * str );
JIMT

回答:


56
func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseIntは常に戻ります int64

bitSize値の範囲を定義します。sに対応する値を、指定されたサイズの符号付き整数で表すことができない場合、err.Err = ErrRange。

http://golang.org/pkg/strconv/#ParseInt

type int int

intは、少なくとも32ビットのサイズの符号付き整数型です。ただし、これは別個のタイプであり、たとえばint32のエイリアスではありません。

http://golang.org/pkg/builtin/#int

したがってint、将来的に、またはintCのような一部のシステムでは、32ビットより大きくなる可能性があります。

一部のシステムでint64int32、64ビット整数でしか動作しないためよりも高速になる可能性があると思います。

bitSizeが8の場合のエラーの例を次に示します。

http://play.golang.org/p/_osjMqL6Nj

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, err := strconv.ParseInt("123456", 10, 8)
    fmt.Println(i, err)
}

22
実際には、移動は、通常使用int64のためintのamd64 GOARCH上とint32のためにint32ビットのGOARCHesに。少なくともデフォルトのコンパイラでは、gccgoについてはよくわかりません。したがって、「int32ビットより大きくなる可能性があります...」は単なる推測ではなく、64ビットのコンパイルターゲットは一般にGoのメインブランチと見なされているため、実際にはかなり可能性があります。
linearZoetrope 2014

12
「実際には、Goは通常amd64 [..]のintにint64を使用します」-より正確には、intは常にプロセッサのビットサイズに等しくなります。つまり、64ビットシステムでは64ビット、32ビットシステムでは32ビットです。コンパイル対象に応じて、int32またはint64のエイリアスだと思います(エイリアスとして実装されていなくてもかまいません)。
zupa 2015年

@zupa「intは常にプロセッサのビットサイズに等しい」のソース/リファレンスは何ですか?
kapad

29

パッケージstrconv

func ParseInt

func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseIntは、指定された基数(2〜36)の文字列sを解釈し、対応する値iを返します。base == 0の場合、baseは文字列のプレフィックスによって示されます。「0x」の場合はbase 16、「0」の場合はbase 8、それ以外の場合はbase10です。

bitSize引数は、結果が収まらなければならない整数型を指定します。ビットサイズ0、8、16、32、および64は、int、int8、int16、int32、およびint64に対応します。

ParseIntが返すエラーは、具体的なタイプ* NumErrorであり、err.Num = sが含まれます。sが空であるか、無効な数字が含まれている場合、err.Err = ErrSyntax; sに対応する値を、指定されたサイズの符号付き整数で表すことができない場合、err.Err = ErrRange。

ParseInt常にint64値を返します。応じてbitSize、この値はに収まるintint8int16int32、またはint64。で指定されたサイズの符号付き整数で値を表すことができない場合はbitSizeerr.Err = ErrRange

Goプログラミング言語仕様

数値タイプ

nビット整数の値はnビット幅で、2の補数演算を使用して表されます。

int8        the set of all signed  8-bit integers (-128 to 127)
int16       the set of all signed 16-bit integers (-32768 to 32767)
int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

実装固有のサイズを持つ事前に宣言された数値型のセットもあります。

uint     either 32 or 64 bits
int      same size as uint

int実装に応じて、32ビットまたは64ビットのいずれかです。通常、32ビットコンパイラの場合は32ビット、64ビットコンパイラの場合は64ビットです。

intまたはのサイズを確認するにはuint、を使用しますstrconv.IntSize

パッケージstrconv

定数

const IntSize = intSize

IntSizeintまたはuint値のビット単位のサイズです。

例えば、

package main

import (
    "fmt"
    "runtime"
    "strconv"
)

func main() {
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

出力:

gc amd64 linux
64

7

strconv.ParseIntと友人は、APIをクリーンでシンプルに保つために64ビットバージョンを返します。それ以外の場合は、可能な戻り値の型ごとに個別のバージョンを作成する必要があります。またはinterface{}、を返します。これは、型アサーションを実行する必要があります。どれも理想的ではありません。

int64サポートされている64ビットまでの任意の整数サイズを保持できるため、が選択されています。関数に渡すビットサイズにより、値が正しい範囲に適切にクランプされます。したがって、戻り値に対して型変換を行うだけで、必要な整数型に変換できます。

差としてintint64、これは、アーキテクチャに依存しています。intは、コンパイル対象のアーキテクチャに応じて、32ビットまたは64ビット整数のエイリアスにすぎません。

目の肥えた人のために:戻り値は符号付き整数です。strconv.ParseUint符号なし整数には別の関数があり、uint64上記で説明したのと同じ理由を返し、それに従います。


4
私がこれまで見てきたことから、これはほとんど正しいですが、int単なるエイリアスではないと思います-実際には別個のタイプです。golang.org/pkg/builtin/#int
Isaac Dontje Lindell

確かに。Goは実際には型のエイリアシングを行いません。のようなものtype int int32は、一意の別個のタイプとして扱われます。特にint、新しいメソッドを適用することで、タイプに新しい機能を定義できるためです。
jimt 2014


0

Go langでは、各タイプは個別のデータタイプと見なされ、基本タイプと互換的に使用することはできません。例えば、

type CustomInt64 int64

上記の宣言では、CustomInt64と組み込みのint64は2つの別個のデータ型であり、互換的に使用することはできません。

int、int32、およびint64の場合も同じです。これらはすべて別個のデータ型であり、互換的に使用することはできません。int32が32の整数型である場合、int64は64ビットであり、汎用int型のサイズはプラットフォームに依存します。32ビットシステムでは32ビット幅、64ビットシステムでは64ビット幅です。したがって、int、uint、floatなどの一般的なデータ型を指定するときは注意して具体的にする必要があります。コードのどこかで問題が発生し、別のプラットフォームでアプリケーションがクラッシュする可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.