原文链接:http://blog.polossk.com/201405/c-plus-plus-g-plus-plus

G++?

首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已。

那么他们之间的区别是什么?

在提交题目中的语言选项里,G++和C++都代表编译的方式。准确地说,选择C++的话,意味着你将使用的是最标准的编译方式,也就是ANSI C++编译。如果你使用的是G++的话,意味着你将使用GNU项目中最平凡适用人群最多的编译器(其实也就是我们熟悉的Code::Blocks的自带的编译器,Windows环境里一般是MinGW下的gcc,Linux中的gcc和前者基本是一个东西)进行编译。类似的还有选择C和GCC,前者是标准C编译器编译,后者同样是用gcc来编译。

编译器的差别——编译器的优化

当然,很多时候我们有的代码用C++提交通过了,但是G++却失败了呢?众所周知,不同的编译器,会对代码做出一些不同的优化。举一个最简单的例子。针对单个语句(注意,是单个语句,不是包含在语句中的那种前++和后++):

a: a++;b: ++a;

一般的讲,我们都知道,这两条语句的最终结果是一样的,就是a自己增加了1。但是,两者的差距还是有的。如果从标准C的角度去理解。a++这个语句等同于

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。(C语言中的%f和%lf搞不明白)

当然对于另外一个特殊的类型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的那一套标识符系统。

当然还有更简单的方法,就是直接用输入输出流在控制输入输出,这样更省事,而且跨平台性能更好,不会出现这种因为标识符而出错的情况。

列个表格出来就是这个样子的:

double f; G++提交 C++提交 本机gcc测试 最安全的方法
输入 scanf("%lf", &f); scanf("%lf", &f); scanf("%lf", &f); cin >> f;
输出 printf("%f", f); printf("%lf", f); printf("%lf", f); cout << f;

大概就是这么多了,希望大家避免这种错误的发生。

【转】OJ提交题目中的语言选项里G++与C++的区别的更多相关文章

  1. OJ提交题目中的语言选项里G++与C++的区别

    一.OJ提交题目中的语言选项里G++与C++的区别 http://www.th7.cn/Program/cp/201405/199001.shtml 首先更正一个概念,C++是一门计算机编程语言,G+ ...

  2. OJ提交题目中的语言选项里G++与C++的区别(转)

    G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已. 那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式. ...

  3. OJ提交题目中的语言选项里G++与C++的区别(转载)

    原文链接:http://blog.polossk.com/201405/c-plus-plus-g-plus-plus G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编 ...

  4. Windows Store App 全球化:应用中设置语言选项

    当开发者将开发的应用上传到Windows应用商店以后,使用Windows 8系统的用户可能会看到并下载这些应用,而这些用户所在的区域或者所使用的语言可能都不相同,如果他们在使用应用程序时希望改变应用显 ...

  5. 【转】OJ提交时G++与C++的区别

    关于G++ 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已.那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式. ...

  6. 详解OJ(Online Judge)中PHP代码的提交方法及要点【举例:ZOJ 1001 (A + B Problem)】

    详解OJ(Online Judge)中PHP代码的提交方法及要点 Introduction of How to submit PHP code to Online Judge Systems  Int ...

  7. 【九度OJ】题目1473:二进制数 解题报告

    [九度OJ]题目1473:二进制数 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1473 题目描述: 大家都知道,数据在计算机里中存 ...

  8. 【九度OJ】题目1072:有多少不同的面值组合? 解题报告

    [九度OJ]题目1072:有多少不同的面值组合? 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1072 题目描述: 某人有8角的邮票 ...

  9. Linux: 介绍make menuconfig中的每个选项含义【转】

    转自:http://blog.csdn.net/gaoyuanlinkconcept/article/details/8810468 介绍make menuconfig中的每个选项含义 Linux 2 ...

随机推荐

  1. Linux学习笔记 - Shell 函数的使用

    基本语法 funname () { action; return -)):如果不加,将以最后一条命令运行结果,作为返回值. } 示例1:定义并调用无返回值的函数 #!/bin/bash a= b= c ...

  2. Java复习——反射和泛型的复习

    反射 Class类 一个类被类加载器加载到内存之中,占有一片区域,这个空间里的内容就是类的字节码,不同的类的字节码是不一样的,这一个个空间页可以使用类来表示,这就是Class类. 根据这个概念可知:不 ...

  3. 3d标签云(JS版)

    http://www.miaov.com/miaov_demo/3dLable/miaov_demo.html http://www.lijian.net/p/windstagball/index.h ...

  4. 数据结构和算法之单向链表二:获取倒数第K个节点

    我们在做算法的时候或多或少都会遇到这样的问题,那就是我们需要获取某一个数据集的倒数或者正数第几个数据.那么今天我们来看一下这个问题,怎么去获取倒数第K个节点.我们拿到这个问题的时候自然而然会想到我们让 ...

  5. 脱壳系列(一) - CrypKeySDK 壳

    程序: 运行 用 PEiD 载入程序 PEid 显示找不到相关的壳 脱壳: 用 OD 载入程序 这个是壳的入口地址 因为代码段的入口地址为 00401000 这三个是壳增加的区段 按 F8 往下走程序 ...

  6. 深入浅出 Java Concurrency (14): 锁机制 part 9 读写锁 (ReentrantReadWriteLock) (2)

      这一节主要是谈谈读写锁的实现. 上一节中提到,ReadWriteLock看起来有两个锁:readLock/writeLock.如果真的是两个锁的话,它们之间又是如何相互影响的呢? 事实上在Reen ...

  7. [Z]用subcaption包排版子图(表)与图(表)格式设置

    很不错的一篇文章,可以进一步参考caption和subcaption的文档: http://www.peteryu.ca/tutorials/publishing/latex_captions

  8. Strem String Memory TStringStream

    System.SysUtils 一.TStringStream方法 Strem>String TMemoryStream to String stm: TStream; ss: TStringS ...

  9. i++的原子性问题

    一.什么是原子性 简单的可以理解为:操作是不可再分割的,比如: int i=0; 但是i++的操作是可以再分的,比如: i++ //分解后 i=i+i 上面的代码在多线程环境下取值是有问题的,比如: ...

  10. 利用maven实现差异化配置

    回顾过去 生产环境,测试环境,开发环境在不同的环境下会有各种各样的配置,比如数据库链接地址,账户名,密码等等.不同环境下都需要配置,但是配置却又不同.以前分享过一篇文章,介绍了我之前A公司的差异化配置 ...