【转】OJ提交时G++与C++的区别
关于G++
首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已。那么他们之间的区别是什么?
在提交题目中的语言选项里,G++和C++都代表编译的方式。准确地说,选择C++的话,意味着你将使用的是最标准的编译方式,也就是ANSI C++编译。如果你使用的是G++的话,意味着你将使用GNU项目中最平凡适用人群最多的编译器(其实也就是我们熟悉的Code::Blocks的自带的编译器,Windows环境里一般是MinGW下的gcc,Linux中的gcc和前者基本是一个东西)进行编译。类似的还有选择C和GCC,前者是标准C编译器编译,后者同样是用gcc来编译。
编译器的差别——编译器的优化
当然,很多时候我们有的代码用C++提交通过了,但是G++却失败了呢?众所周知,不同的编译器,会对代码做出一些不同的优化。举一个最简单的例子。针对单个语句(注意,是单个语句,不是包含在语句中的那种前++和后++):
1
2 a: a++;
b: ++a;
一般的讲,我们都知道,这两条语句的最终结果是一样的,就是a自己增加了1。但是,两者的差距还是有的。如果从标准C的角度去理解。a++这个语句等同于
1 a: a = a +1
也就是说,我是先调用,再自增。在调用过程中,会申请一个新的数据地址,用于存放临时的变量a’,然后在把a’加1,之后在把a’赋值给a。但是++a这个语句不需要这么麻烦。因为他是先自增,后调用,也就是省去了申请新地址的功夫。所以理论上,二者的时间消耗是有差异的,如果你是使用标准C的编译方式,就可以发现这个差异。毕竟,申请临时内存这个操作耗费的时间,远远比令已知内存的数据进行一个改变要长的多。但是编译器的优化就体现在了这种本身结果相同却耗时有差异的地方。如果你使用gcc来编译,结果你会发现前++与后++二者基本上没有差异。这就是编译器的优化中的冰山一角了。事实上还有很多优化的地方。
为什么G++提交WA了?
好吧回到现实中来。我昨天在做poj 3122这道题的时候,再一次的遇到了G++WA;C++AC的尴尬局面。为什么呢?其实这个也算是编译器优化的一部分,那就是精度缺省。
众所周知,long long类型,作为一个在C/C++11才被确认为基本数据类型的一个数据类型,在不同的环境下,他的类型标识符是不同的。也就是我们津津乐道的%lld 和 %I64d了。同样,double类型也是一个有趣的类型。double类型其实准确地说是双精度型,他的内存长度一般是比float类型(单精度型)的多了一倍,有的时候很早的标准里是把double称为long float的。所以说就有了为什么float类型用%f,double用%lf。但是由于现在不是以前的那种一个内存条就几兆,多开一个double就会超内存的年代了,所以double还有float在gcc中被自动优化。
在用scanf读数据时,为了与float区分,使用%lf。
在用printf写数据时,由于实质上,double和float是同一个类型,只不过内存占用有差异而已,他们的标识符都是%f,注意,这个和标准C不同,这里的都是%f。
当然对于另外一个特殊的类型long double虽然不常用,但是编译器依旧在支持,这里有个插曲,理论上long double应该是两倍的double(类似long long和int的关系,因为long和int其实是一个东西)。
但是实际上,long double很奇怪的是一个10字节的怪物,他有两个空余字节,是怎么改动都不会发生变化的。输入输出的标识符都是%Lf,大写的L。
但是这里又有问题了,为什么我在本地用%f会WA,在OJ上用%f会AC?
因为我们本机如果使用的是Windows下的Code::Blocks这款IDE的话,编译器也就是MinGW这个东西。事实上,为了尽量保持gcc的跨平台性,MinGW在某些地方是直接用了MSVC的东西的,而对我们影响最大的就是这个标识符的问题。简单的说,如果你是要在本机测试,那么最好,请使用标准C的那个标识符系统;如果你要提交代码,那么请改成gcc的那一套标识符系统。再有就是编译器版本的问题,现在的MinGW版本已经到了4.8,但是POJ上仍然使4.4,所以低版本的编译器同样会有一些不寻常的问题。
当然还有更简单的方法,就是直接用输入输出流在控制输入输出,这样更省事,而且跨平台性能更好,不会出现这种因为标识符而出错的情况。
列个表格出来就是这个样子的:
double f; | POJ G++提交 | POJ C++提交 | 本机测试(MinGW GCC 4.8) | 最安全的方法 |
输入 | scanf(“%lf”, &f); | scanf(“%lf”, &f); | scanf(“%lf”, &f); | cin >> f; |
输出 | printf(“%f“, f); | printf(“%lf”, f); | printf(“%lf“, f); | cout << f; |
大概就是这么多了,希望大家避免这种错误的发生。
--------------------------------------------------------------以上内容为转载-----------------------------------------------------------------------
补充一下...cin和cout在这一点上比较安全,但是读取速度却比scanf和printf慢很多,在ACM比赛中,用cin和cout当然有可能导致TLE啦、
事实上,cin慢是有原因的,其实默认的时候,cin与stdin总是保持同步的,也就是说这两种方法可以混用,而不必担心文件指针混乱,同时cout和stdout也一样,两者混用不会输出顺序错乱。正因为这个兼容性的特性,导致cin有许多额外的开销,如何禁用这个特性呢?只需一个语句 std::ios::sync_with_stdio(false); ,这样就可以取消cin于stdin的同步了。
std::ios::sync_with_stdio(false);
std::cin >> n;
std::cout << n;
速度基本可以达到csanf和printf。
希望有所帮助~ 谢谢。
【转】OJ提交时G++与C++的区别的更多相关文章
- oj提交时常见错误归纳
Presentation Error: 常见的PE错误应该有以下的几种情况: 每行输出之后有空行 每两行输出之间有空行 一行中,每个输出数字(或字符串,等)之间有空格 一行中,每个输出数字(或字符串, ...
- OJ上 编译器 G++和C++的区别
原文 :http://blog.csdn.net/febr2/article/details/52068357 编译时的差异: 编译器优化不同: 举个栗子: ①: a++ ②: ++a 从标准C的角度 ...
- OJ提交题目中的语言选项里G++与C++的区别
一.OJ提交题目中的语言选项里G++与C++的区别 http://www.th7.cn/Program/cp/201405/199001.shtml 首先更正一个概念,C++是一门计算机编程语言,G+ ...
- jQuery判断 form表单提交时一些文本框的判断
一: form表单提交时如果表单里有input标签为空那么不提交form表单. <head> <script type="text/javascript"> ...
- svn提交时提示 Aborting commit: remains in conflict 解决办法
出现在rename一个目录时,再提交时一直报错 Aborting commit: remains in conflict 使用右键菜单 svn - resolve 即可解决.用cleanup之类的都没 ...
- git提交时支持文件名大小写的修改
在windows环境下,git提交文件时,默认对文件名大小写不敏感,若修改了文件名字的大小写,可能会导致提交时没有记录,文件名修改不成功.网上搜集了几种解决方法,现总结下: 1. 修改git conf ...
- CastleActiveRecord在多线程 事务提交时数据库资源竞争导致更新失败的测试结果记录
CastleActiveRecord 经过测试,隔离级别: // 摘要: , , , , , , , ...
- SVN(TortoiseSVN)提交时忽略bin跟obj目录
SVN(TortoiseSVN)提交时忽略bin和obj目录 一般协作开发情况下,有意思无意将bin和obj目录添加到版本管理中是很烦人的事儿,在VS中不断地编译程序集和提交将带来版本暴增问题.如果你 ...
- svn提交时强制添加注释 (转)
SVN提交时,如果没有注释,在查阅历史时,会非常不方便.因此我们需要有一个让程序员提交代码时,强制添加注释的规则.下面看看在SVN中怎么实现. 1. 推荐使用VisualSVN作为服务端(免费下载地址 ...
随机推荐
- 关于linux上部署定时python脚本
遇到的坑: Python脚本中的文件操作,最好都用绝对路径, 文件头上写 #!/usr/local/bin/python3.6 ----------------------------------- ...
- ISP PIPLINE (四) Demosaic
what is the Demosaic? CMOS/CCD在成像时,CFA(color filter array),CFA过滤不同频段的光,因此,Sensor的输出的RAW数据信号包含了3个通道的信 ...
- MyBatis3系列__01HelloWorld
# MyBatis作为一个ORM框架,其重要程度不用过多介绍.下面开始一起学习吧:本博客的编程方法与MyBatis官方文档基本一致:## 1.创建一个数据库mybatis_learn以及对应的表tbl ...
- d4-01
一.字典 1.1 var dict = {"name":"zhangsan"} 定义字典 1.2 dict.name 取得name的值 1.3 del ...
- Python 遇到的坑
1. 循环导入 AB 互相引用,或者 中间掺入了更复杂的一些--用局部导入解决
- [LeetCode] Largest Triangle Area 最大的三角区域
You have a list of points in the plane. Return the area of the largest triangle that can be formed b ...
- Java课程寒假之回答问题:如何将你的兴趣化为可以立足于社会的资本
在学校的时候干过几次兼职,算是无聊时候的外快吧,有一次是去辅导机构,在考试期间监考学生,前后大概四个小时,最后拿了四十五并且管了一顿饭,不得不说,小学生是真的皮,考试的时候有的爱讲话,有的是写完之后开 ...
- 十四、JavaWeb监听器
JavaWeb监听器 三大组件: l Servlet l Listener l Filter Listener:监听器 初次相见:AWT 二次相见:SAX 监听器: l 它是一个接口,内容由我们来实现 ...
- node 学习(一)
什么是 Node.js Node.js就是运行在服务端的JavaScript. Node.js是一个基于Chrome JavaScript运行时建立的一个平台. Node.js是一个事件驱动 I/O ...
- waitpid 函数详解
关于Linux中waitpid函数的一些使用说明: #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t waitpid( ...