C++中的long long与__int64

目录
  • 1、long long 和 __int64
  • 2、历史遗留问题
  • 3、cin、cout和scanf、printf的选择问题

1、long long 和 __int64

C++ Primer当中提到的64位的int只有long long,但是在实际各种各样的C++编译器当中,64位的int一直有两种标准。一种是long long,还有一种是__int64,非主流的VC甚至还支持_int64。

对于一般的C++开发者来说,其实这个问题不那么要紧,因为在实际开发当中,绝大多数情况使用32位的int就足够应付了。很少会出现超过int范围的情况,但是对于算法玩家来说,这是一个必须考量的问题。因为很多题目会故意把范围弄得很大,考察选手对于数据范围的敏感。

关于long long__int64,我们有非常多的问题要讨论,我们一个一个来说。

2、历史遗留问题

首先是聊聊这个问题的背景,为什么会有两种标准呢?这并不是C++的标准不严谨,或者是各大编译器乱来,背后是有一个历史遗留问题的。

long long最早是C99标准引进的,然而VC6.0推出于1998年,在C99标准之前。所以当时微软就自己搞出来一个变量叫做__int64来表示64位整数。很多同学使用的第一个C++的编译器就是VC6.0,所以记得在VC6.0当中要使用__int64而非long long。

既然VC6.0搞出了__int64,那么微软后续的C++版本显然就必须要兼容它。所以在win系统当中,这个__int64的变量类型就一直沿用了下来。当然,由于C++标准的更新,当然最新的visual studio已经支持long long了。

GCC并不是基于windows系统的,自然支持long long。win平台下的一些其他IDE如dev C++ CodeBlocks等也支持long long,因为它们为了和微软的系统兼容,所以也支持__int64。所以一个比较简单的区分方法是,判断编译器运行的操作系统是否是windows,如果是windows使用__int64,否则使用long long

3、cin、cout和scanf、printf的选择问题

这个问题对于C++开发工程师来说同样不是个问题,没有任何选择的必要,无脑用cincout就完事了。但对于算法竞赛玩家来说,这依然是一个要考虑的问题。

因为在算法竞赛当中,尤其是当数据量很大的时候,读入和输出占据的时间是非常可观的。看起来只是cin coutscanfprintf的差别,但是两者的性能差异非常大。

我曾经做过实验,同样的数据,使用scanfprintf的效率大约是cincout的十倍以上。在小数据量的时候当然没有差别,但数据量很大的时候影响非常大。很有可能导致同样的题目,同样的算法,别人通过了,但是我们却超时了的情况。

关于性能差异的原因,主要有两种解释。一种解释是说cin为了与scanf混用,而不用担心指针混乱,加上了绑定,总是会与stdin保持同步。正是这一步操作消耗了大量的时间。同理,cout也会有类似的问题。第二种解释是cout在输出之前会把要输出的内容先存入缓存区,中间多了一个步骤,也会带来性能的降低。

关于cin与stdin同步带来的开销,我们是有办法解决的,只需要在加上这一行代码:

std::ios::sync_with_stdio(false);

这行代码的意思是取消cincoutstdinstdout的指针同步,会使得cincout的性能大大提升,达到和scanfprintf相差无几的程度。当然,更好的方法是使用scanfprintf代替。

而要使用scanfprintf又有一个问题,它们是C语言的标准输入输出方式,需要提供标识符来代表变量的类型,那么问题来了long long__int64的标识符是什么呢?

这个其实一查就知道了,long long的标识符是lld,所以我们使用scanf读入一个long long类型的数写成:

long long a;
scanf("%lld", &a);

__int64的标识符是I64d,注意这里是大写的i,不是l。

__int64 a;
scanf("%I64d", &a);

但是这里面有一个很大的坑点,前面说了,目前在windows平台的编译器已经兼容了long long类型。但是即便如此,在2013年之前的版本里,我们输出的时候还是要使用%I64d,这是因为微软提供的msvcrt.dll库只支持%I64d的方式。相当于从底层上断绝了使用%lld输出的可能。2013年微软修复了这个问题,添加了对 %lld 的支持。

所以比较简单的区分方法就是看操作系统,如果是windows系统,那么一律使用__int64准没错。如果是linux或者是Mac系统,那么统一使用long long

我在网上找到了大神做的总结表,也可以直接参考下表:

变量定义 输出方式 gcc(mingw32) g++(mingw32) gcc(linux i386) g++(linux i386) MicrosoftVisual C++ 6.0
long long “%lld” 错误 错误 正确 正确 无法编译
long long “%I64d” 正确 正确 错误 错误 无法编译
__int64 “lld” 错误 错误 无法编译 无法编译 错误
__int64 “%I64d” 正确 正确 无法编译 无法编译 正确
long long cout 非C++ 正确 非C++ 正确 无法编译
__int64 cout 非C++ 正确 非C++ 无法编译 无法编译
long long printint64() 正确 正确 正确 正确 无法编译

到此这篇关于C++中的long long__int64的文章就介绍到这了,更多相关C++ long long __int64内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ 中的INT_MAX,INT_MIN数值大小操作

    int占4字节32位,根据二进制编码的规则, INT_MAX = 2^31-1=2147483647 INT_MIN= -2^31=-2147483648 C/C++中,所有超过该限值的数,都会出现溢出,出现warning,但是并不会出现error. 如果想表示的整数超过了该限值,可以使用长整型long long 占8字节64位. 补充:C++ 数值最大最小标识符一网打尽,INT_MIN/ INT_MAX/LONG_MIN/LONG_MAX 等等 我就废话不多说了,大家还是直接看代码吧~ Con

  • C++ LARGE_INTEGER解析与使用案例详解

    这里解释前面碰到的LARGE_INTEGER结构.与可能的误解不同,64位数据并非要在64位操作系统下才能使用.在VC中,64位数据的类型为__int64.定义写法如下:     __int64 file_offset     上面之所以定义的变量名为file_offset,是因为文件中的偏移量是一种常见的要使用64位数据的情况.同时,文件的大小也是如此(回忆上一小节中定义的文件大小).32位数据无符号整型只能表示到4GB.而众所周知,现在超过4GB的文件绝对不罕见了.但是实际上__int64这

  • C++ 字符串string和整数int的互相转化操作

    一.string转int的方式 1.采用最原始的string, 然后按照十进制的特点进行算术运算得到int,但是这种方式太麻烦,这里不介绍了. 2.采用标准库中atoi函数. string s = "12"; int a = atoi(s.c_str()); 对于其他类型也都有相应的标准库函数,比如浮点型atof(),long型atol()等等. 3.采用sstream头文件中定义的字符串流对象来实现转换. istringstream is("12"); //构造输

  • C++ 输入scanf()和输出printf()的操作

    在C语言中是用printf函数进行输出,用scanf函数进行输入的.C++保留了C语言的这一用法,在此只作很简单的介绍. scanf函数一般格式是: scanf(格式控制, 输出表列) printf函数的一般格式是 printf(格式控制,输出表列) [例3.4]用scanf和printf函数进行输入和输出. #include <iostream> using namespace std; int main( ) { int a; float b; char c; scanf("%d

  • C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)

    目录 1. c强制转换与c++强制转换 2. static_cast.dynamic_cast.const_cast.reinterpret_cast dynamic_cast const_cast reinterpret_cast 3. c++强制转换注意事项 1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 c++除了能使用c语言的强制类型转

  • c++ 解决无法打印uint8_t 类型变量的问题

    将uint8_t 转化为unsigned 类型 使用一元运算符+(和- 运算符对应) 测试代码如下 #include <cstdint> #include <iostream> #include <typeinfo> int main() { std::uint8_t uint8_num = 10; std::cout << "uint8_t num is " << uint8_num << std::endl;

  • 用C++的odeint库求解微分方程

    目录 1.集成方程 2.求解单摆模型 2.1 微分方程标准化 2.2 代码实现 微分方程的标准形式为: 即:\dot{\boldsymbol{x}} = \boldsymbol{f}(\boldsymbol{x}, t),\, \boldsymbol{x}(0) = \boldsymbol{x_0} 这是一阶微分方程组, \boldsymbol{x} 和 \boldsymbol{f}(\boldsymbol{x}, t) 均为向量.如果要求解高阶微分方程,需要先转换成一阶微分方程组后再用odei

  • C/C++ int数与多枚举值互转的实现

    在C/C++在C/C++的开发中经常会遇到各种数据类型互转的情况,正常的互转有:单个枚举转int数,int数转float数,float数转double数等.但是我们有时也会遇到多个枚举值与数字互转的情形(例如多个算法类型枚举开启标志转成数字,这个数字来表示多个标志位,按位来表示).这样一个数字就能表示很多个标志位了,针对内存较少的嵌入式设备,这么操作可以达到节约内存消耗,提高程序运行效率的目的. Demo示例 demo核心知识点:通过位运算符(布尔位运算符:"~"."&

  • C++中的long long与__int64

    目录 1.long long 和 __int64 2.历史遗留问题 3.cin.cout和scanf.printf的选择问题 1.long long 和 __int64 在C++ Primer当中提到的64位的int只有long long,但是在实际各种各样的C++编译器当中,64位的int一直有两种标准.一种是long long,还有一种是__int64,非主流的VC甚至还支持_int64. 对于一般的C++开发者来说,其实这个问题不那么要紧,因为在实际开发当中,绝大多数情况使用32位的int

  • 深入解析C++编程中__alignof 与__uuidof运算符的使用

    __alignof 运算符 C++11 引入 alignof 运算符,该运算符返回指定类型的对齐方式(以字节为单位).为实现最大的可移植性,应使用 alignof 运算符,而不是特定于 Microsoft 的 __alignof 运算符. 返回一个 size_t 类型的值,该值是类型的对齐要求. 语法 __alignof( type ) 备注 例如: Expression 值 __alignof( char ) 1 __alignof( short ) 2 __alignof( int ) 4

  • 探究C++中string类的实现原理以及扩展使用

    C++程序员编码过程中经常会使用string(wstring)类,你是否思考过它的内部实现细节.比如这个类的迭代器是如何实现的?对象占多少字节的内存空间?内部有没有虚函数?内存是如何分配的?构造和析构的成本有多大?笔者综合这两天阅读的源代码及个人理解简要介绍之,错误的地方望读者指出. 首先看看string和wstring类的定义: typedef basic_string<char, char_traits<char>, allocator<char> > string

  • 解析wprintf 中使用%I64d格式化输出LONGLONG的详细介绍

    wprintf 中使用%I64d格式化输出LONGLONG 在写某个程序时,因为需要用到一个大的整数,就是要了LONGLONG型: 复制代码 代码如下: LONGLONG nLarge; 但是格式化时不知道应该用什么字符,用 %d,%l都不行.LONGLONGLONGLONG其实就是int64类型.在winnt.h可以看到: 复制代码 代码如下: typedef __int64 LONGLONG; 所以要想输出就要看__int64使用什么格式符了.通过查MSDN中,发现是:I64.在格式化输出则

  • OJ中G++和C++的区别

    首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已. 那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式.准确地说,选择C++的话,意味着你将使用的是最标准的编译方式,也就是ANSI C++编译.如果你使用的是G++的话,意味着你将使用GNU项目中最平凡适用人群最多的编译器(其实也就是我们熟悉的Code::Blocks的自带的编译器,Windows环境里一般是MinGW下的gcc,Linux中的gcc和前者基本是

  • 一文读懂c语言结构体在单片机中的应用

    Struck 看到单片机中有很多struck 的应用,但是呢我当初学C语言的时候又没有很认真的去学习,今天复习下,写一篇小小的交流,希望能够给大家带来帮助. 1.struck的定义 /***********方式一**********/ struct Book { char title[128]; char aurhor[40]; float price; unsigned int date; char pubilsher[40]; }; /*定义了Book这个模板*/ struct Book b

  • 一篇文章带你了解论C语言中算法的重要性

    目录 一.问题一(打印阶乘) 问题描述: 问题分析: 解决方案: 1.让我们检查一下结果,发现问题很有可能是循环的时候没有循环本身 2.这里要引入C++中STL库的一个知识点 二.问题二(比较多项式计算时间) 问题描述: 问题分析: 解决方案: 总结 一.问题一(打印阶乘) 问题描述: 打印出数字一到数字20的阶乘 一开始,我总会多打印出一个1,这令我十分苦恼,并且从n等于13开始,数据就开始溢出 问题分析: 让我们分析一下问题,这里面存在着两个问题: 1.多打印出一个1 2.数据溢出 解决方案

  • C++中的整型

    目录 1.整型 2.short.int.long和long long 3.位与字节 4.初始化 5.无符号类型 1.整型 整型即整数,与小数对应. 许多语言只能表示一种整型(如Python),而在C++当中根据整数的范围提供了好几种不同的整型. C++的基本整型有char.short.int.long,在C++ 11标准中,新增了long long.在部分编译器当中不支持long long,而支持__int64.稍后会有单独的文章对此进行解释和补充说明. 其中char类型有一些特殊属性,通常被用

  • java高级用法之JNA中使用类型映射

    目录 简介 类型映射的本质 TypeMapper NativeMapped 总结 简介 JNA中有很多种映射,library的映射,函数的映射还有函数参数和返回值的映射,libary和函数的映射比较简单,我们在之前的文章中已经讲解过了,对于类型映射来说,因为JAVA中的类型种类比较多,所以这里我们将JNA的类型映射提取出来单独讲解. 类型映射的本质 我们之前提到在JNA中有两种方法来映射JAVA中的方法和native libary中的方法,一种方法叫做interface mapping,一种方式

  • angular中不同的组件间传值与通信的方法

    本文主要介绍angular在不同的组件中如何进行传值,如何通讯.主要分为父子组件和非父子组件部分. 父子组件间参数与通讯方法 使用事件通信(EventEmitter,@Output): 场景:可以在父子组件之间进行通信,一般使用在子组件传递消息给父组件: 步骤: 子组件创建事件EventEmitter对象,使用@output公开出去: 父组件监听子组件@output出来的方法,然后处理事件. 代码: // child 组件 @Component({ selector: 'app-child',

随机推荐