在 golang 里面,有 int64,int32,int 这 3 种数据类型。
int64: 占 64 位的整数数据类型
int32: 占 32 位的整数数据类型
int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位
于是我就纳闷了,int 这个数据类型不是埋坑吗?不同的处理器上面可能导致不同的运行结果,那设计这个数据类型的意义是啥呢?为啥不只保留 int64 和 int32,由程序员指定长度,保证运行结果的一致性
我 google 查了很久,没找到相关的资料,还望了解的老哥赐教
1
xuanbg 2021-01-14 15:27:25 +08:00
因为程序员往往不能预知他写的代码会在什么环境下运行……
|
2
wudicgi 2021-01-14 15:30:01 +08:00
老哥没见过 C 语言里的 int, int32_t, int64_t ?
|
3
jiangwei2222 OP @xuanbg #1 就因为不能预知,所有指定使用 int64 或者 int32 不更加保险吗
|
4
no1xsyzy 2021-01-14 15:33:22 +08:00
有一个可能性是为了效率,在 64 位上为了 int32 需要 runtime 手动限制只使用低 32 位,可能需要手动调整溢出 flag ?
32 位上 int64 是必然需要模拟的…… |
5
ruyu 2021-01-14 15:35:32 +08:00 2
在不 care 最大值的时候使用 int, 让所有的 CPU 都开心.
|
6
no1xsyzy 2021-01-14 15:36:01 +08:00
如果说你肯定该数远远达不到 int32 和 int64 (比如一个 flag,只能取 012,其他均视为未定义行为),那么这个 overhead 就比较明显了。
而如果你有一百万个这样的数…… |
7
zoharSoul 2021-01-14 15:36:56 +08:00
我也挺纳闷的
|
8
icexin 2021-01-14 15:38:43 +08:00 3
int 跟机器字长一致,这样可以获取最大的执行效率。在不关心数值范围的场景下 int 足够了,比如数组下标。相反如果你在 32 位机器上使用 int64,本来一条指令的事情要变成多条指令。
int32 和 int64 这些一般用于编解码、底层硬件相关,或者是数值范围敏感的场景。 |
9
xuanbg 2021-01-14 15:41:33 +08:00
@jiangwei2222 如果你指定 x64,在 x86 平台上就跑不起来啦。指定 x86,x64 平台倒是能跑,但性能就浪费了。
|
10
eason1874 2021-01-14 15:49:26 +08:00 1
我的理解相反,int 是平台原生,int32 int64 才是有意设计的
|
11
LANB0 2021-01-14 16:06:00 +08:00
在 golang 里面,有 int64,int32,int 这 3 种数据类型。
int64: 占 64 位的整数数据类型 int32: 占 32 位的整数数据类型 int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位 在 c/c++ 里面,有 long long int,int,long int 这 3 种数据类型。 long long int: 占 64 位的整数数据类型 int: 占 32 位的整数数据类型(32 位及 64 位平台,8 位和 16 位不考虑了) long int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位 实际上,在不需要做存储和通讯协议数据对齐的场景下,long int 是在跨平台情况下效率最高的。 跨平台存储和通讯协议数据对齐场景下,4 字节就固定 int32,8 字节就固定 int64 |
12
teawithlife 2021-01-14 16:14:37 +08:00
看到 C99/C++11 的这些,你会更纳闷的
en.cppreference.com/w/c/types/integer 其实原因很简单,就是为了执行效率,一些情况下,我们并不关心 int 到底是 32 位还是 64 位的,反正都够用,这时候就没必要强制指定位数,而是让编译器自己去自行选择效率最高的位数 |
13
secondwtq 2021-01-14 20:55:38 +08:00 2
仅就 x86 而言,int64 还真不一定比 int32 快
“快不快”不仅仅是指令支持的问题,数据宽了一倍,占用的缓存空间、内存带宽都加了一倍。如果真有一百万个这样的数,可能还真是 32 位好一点,特别再考虑到 SIMD 的情况下 如果这货的行为真的像楼主说的一样“在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位”的话,那么看 C/C++ 是正解,不过鉴于大道至简的 Go 目标之一就是干死 C++,估计没人会去看的。 C 里面有一个类型叫 size_t,相当于 Go 的 uint,还有个 ptrdiff_t,相当于 Go 里的 int (假设楼主说的行为是对的) size_t 顾名思义,可以装下任何对象的“大小”,比如在 32 位环境下,地址空间中不可能存在多于 2^32 个唯一的对象,一个对象的大小也不可能超过 2^32 字节,所以 size_t 做成 uint32_t 就可以。需要存大小、数量时就用这货。 ptrdiff_t 顾名思义,可以装下任意两个指针相减的结果,需要存偏移时就用这货。(不过 C 标准里面貌似没有保证,毕竟真正存差值需要 wordsize+1 位 ...) 毕竟如果是 32 位环境,用 64 位数存数组有多少个元素实在太过奢侈了,这时候根据大道至简的原则,就可以加一个类型叫 int 。 这只是一个猜想,因为 Go 的所谓 spec 实在太大道至简了: > uint either 32 or 64 bits > int same size as uint 反正在这两句话我是没找着“在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位”的保证。因为他把这玩意写在后面 builtin functions 部分了:“The built-in functions len and cap take arguments of various types and return a result of type int. The implementation guarantees that the result always fits into an int.”,然后就有了这个 https://yourbasic.org/golang/int-vs-int64/ 。也就是说这个类型和它的角色并不直接关联,可能本来设计者的想法就是从 C 里面随便捣鼓来的 ... |
14
secondwtq 2021-01-14 21:10:42 +08:00
噢对了补充下,我知道做优化的时候有至少一种情况会把 32 位数故意 widen 成 64 位,就是频繁转换的时候。
具体来说,是一个循环的 induction variable ( https://en.wikipedia.org/wiki/Induction_variable )被定义为 32 位,但是使用时总是先 cast 成 64 位再使用,这种情况用 64 位数代替原来的 induction variable 可以省去转换的开销,并且就一两个变量一般都放寄存器里面,做起来才值得。 (嘛不过我只是观察到这么一种行为,并没有找到对应的参考,也没有仔细看相关的代码 ...) |
15
douyacun 2021-01-14 22:43:26 +08:00
自 2008 年 1 月起,Ken Thompson 就开始研发一款以 C 语言为目标结果的编译器来拓展 Go 语言的设计思想。
c 有 go 就有了,因为顺手~ grpc 就果断抛弃了 int |
16
jiangwei2222 OP @secondwtq 多谢大佬解释
|
17
INCerry 2021-01-15 13:45:22 +08:00
那你可以用 C# C#在 64 位或者 32 位系统中 int 都是 Int32
|
18
binlearn 2021-01-15 13:58:56 +08:00
如果我没有猜错,这应该是不同平台“字节对齐”的原因。用 int 能保证字节对齐
|
19
coolesting 2021-01-15 20:49:27 +08:00 via Android
类型细分化,按需分配内存,工作更效率,和 rust 的设计同出一策,所以这两门语言在未来肯定会称霸一方。
|