64位 int 占几个字节_谨慎在C++中用int

067b95438c7fd020f151da8adcca0903.png

C++两大原罪:

  • 有符号整数和无符号整数混用
  • 32位整型和64位整型混用

99+warnings关我什么事,能跑就行。

以下这么长,概括起来一句话:这个整型变量会参与到地址运算吗?(对于整型变量这非常常见,例如用作数组以及stl的索引),如果是,那么不要用int了。

原标题说的很绝对,引来了不少没仔细看就开怼的朋友们。为了营造和谐氛围,应该说是“不要乱用int”,或者说是“不要在64位平台上用int索引”。当然标题这样说虽然很绝对却不过分,因为当今编译器和平台普遍都是64位的情况下,int出现经常是乱用,大多数情况可以并且应该被替代为size_t,long long , ptrdiff_t等。受到谭浩强C语言以及各种C/C++入门书的熏陶,不少新手一想到整型,一律使用 int。可能已经注意到,通篇使用int常常会有大片的此类警告:

警告 C26451 算术溢出: 使用 4 字节值上的运算符 + ,然后将结果转换到 8 字节值。在调用运算符 + 之前将值强制转换为宽类型可避免溢出(io.2)。

d8dba9f1f20f21d0ff51f33211bf419f.png

这是64位和32位整型宽度不对齐的警告。这些警告也许不碍事,只碍眼。有强迫症的,可能按照警告的提示加一个强制类型转换,没有强迫症的人直接就忽略了。但是没有任何一个警告是无缘无故的。这些警告不仅意味着程序中的潜在的溢出问题,还意味着无意义的强制类型转换浪费的效率、

下面这个例子:

用 int i作为vector的索引

std

使用 size_t i作为vector的索引

std

前者的坏处是:

  1. 混用有符号无符号整型。vector的索引接受的是无符号整型。你将收到编译器警告,提示可能发生有符号整型到无符号整型的溢出。(当然,通常数组大小不至于超过32位int的范围,你可能会忽略它,但警告还是碍眼的)
  2. 因为vector的索引接受的是size_t类型,在64位平台上,size_t被typedef到unsigned __int64或 unsigned long long。编译器会警告,将发生宽度为4到宽度为8(即32位到64位)的强制类型转换,并有潜在的溢出可能。这时,程序每次执行a[i]=114514,都会将32位的i转换为64位,它们的宽度是不一致的,程序会浪费了额外的类型转换时间。

你优化所需要考虑的,就是减少强制转换,让warnings变成0。

常见误区:能用int就用int,除非int存不下,才用long long int(无论是出于“方便”还是“省内存”)。事实上,在内存资源不紧张的情况下,纠结这个32位和64位对内存资源的占用没有什么意义。甚至在64位平台上,使用32位索引和地址还会出现强制转换,降低程序效率,并且有潜在的溢出风险。

32 位 VS 64 位

32位平台和64位平台最重要的区别是地址和指令的长度不同。在32位平台上,指针是32位的(即sizeof(void*)==4),并且,为了契合32位,stl的容器的大小、索引也都是32位的整型。在64位平台上,指针是64位的(即sizeof(void*)==8),并且stl的容器的大小和索引也都是64位的。特别指出,64位已经非常普及了,64位编译是必须考虑的问题。

有符号无符号
32位intunsigned int
64位long long;
__int64
unsigned long long; unsigned __int64

为了同时兼容32位和64位,还要避免不必要的类型转换,要使用哪种类型?std中已经用宏和typedef为你写好了:

int => ptrdiff_t

usigned int => size_t

ptrdiff_t的意思是“指针之差”,即两个地址运算之差,对应有符号整型;size_t对应无符号整型,他们的宽度是依赖于编译平台的,在32位平台上是32位的,在64位平台是64位的,他们存在于std库中,用宏检查平台,并typedef自对应平台的整型。

结论:

在单纯的数据上(不会参与地址运算的变量)32位和64位运算的性能差别不大,具体使用那种依赖于实际的空间需求,平台,以及编译优化(注意,32位运算真的不一定比64位运算快!float和double也是一样,如果不在意空间而只是为了时间而用float就不必了,double它不更香吗)(如果你得到了long long运算比int慢2倍的结果,请确定你是否使用了32位平台。因为即便有效率差异,也不至于这么大)。

然而在索引访问、指针地址相关的运算上,使用ptrdiff_t和unsigned_int,应当是规范的C++的统一标准。否则混用的话,必然会出现大片的编译器警告,并且降低程序效率。

看了评论后的补充:这是一篇对新手代码规范的建议。在入门后,最有参考价值的是:stackoverflow,cppreference,近年的博客,标准库和专业开源库的源码。对于不确定的标准,尽量不要参考入门书籍,即便书很经典(也正因为它很经典),它可能已经过时了。此外,动手验证疑惑也是有价值的,在不犯低级错误的情况下。

文章中可能有错误,如果你对文章中的观点有不同意见,请先确保你对x86/x64,debug/release有基本的了解。最好请先阅读以下链接,这些内容更为专业,可以充分解决你绝大多数的疑惑,这将节省我们共同的时间。如果你已有了解,并仍然有不同意见,欢迎指正)

cppreference中关于ptrdiff_t, size_t的标准和介绍(c++11),以及和int, unsigned int 的对比。(结论:在stl容器的索引和指针地址运算上,建议使用ptrdiff_t和size_t

std::ptrdiff_t - cppreference.com​en.cppreference.com size_t - cppreference.com​en.cppreference.com

double 和 float 哪个更快(结论:64位平台上通常double更快):

double or float, which is faster?​stackoverflow.com
9ace974c78e4a39a9e9f85756ffc9adb.png
Is using double faster than float?​stackoverflow.com
9ace974c78e4a39a9e9f85756ffc9adb.png
Float or Double?​stackoverflow.com
9ace974c78e4a39a9e9f85756ffc9adb.png

在数据运算上,int 和更长类型的运算,谁更快(结论:using a smaller data type can be a win if your compiler is smart enough to figure out how to use your processor's vector instructions (aka SSE instructions). Modern vector processing units are smart enough to cram eight 16-bit short integers into the same space as two 64-bit long long integers, so you can do four times as many operations at once. 所以小的数据类型在运算中更快):

C++ int vs long long in 64 bit machine​stackoverflow.com
9ace974c78e4a39a9e9f85756ffc9adb.png
  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值