解决跨平台C风格I/O问题

问题描述

这是最为人知的跨平台问题之一

平台

  • Windows下,我们一般使用mingw-gcc,一般使用MSVC风格的I/O
  • Linux下,我们使用原生的gcc,一般使用GNU/ISO风格的I/O

表现

  • 64位整数的I/O问题(signed/unsigned long long)
    • Windows下只能使用%I64d%I64u
    • Linux下使用%lld%llu
  • 扩展精度浮点数的I/O问题(long double)
    • Windows下无法输入/输出long double类型,因为在MSVC中,long double==double
    • Linux下使用%Lf%Lg%Le

解决方法

1. 使用C++流

最简单、安全的方法,使得I/O与平台无关

有的人提到流的效率问题,经测试,在gcc 4.8.4下,文件流并不比stdio慢

比赛中一般使用文件流而不是重定向stdin/stdout,将有更高的效率。

  • Windows下,文件流效率是stdio的数倍
  • Linux下,文件流与stdio基本持平

2. 使用C99/C++11的<inttypes.h>

实现

提供预定义宏,我们常用的有

  • PRIxN:printf
    • PRId64:输出long long
    • PRIu64:输出unsigned long long
  • SCNxN:scanf
    • SCNd64:输入long long
    • SCNu64:输入unsigned long long

使用

1
2
3
4
5
6
7
8
9
#include<stdio.h>
#include<inttypes.h>
int main()
{
long long n;
scanf("%"SCN64d,&n);
printf("%"PRI64d"\n",n);
return 0;
}

不支持long double

3. 使用mingw

在代码中加入#define __USE_MINGW_ANSI_STDIO 1即可,mingw将不使用MSVC而是按照标准C/C++处理I/O。

这是推荐的方法,而且在Linux下也没有副作用。

4. 使用编译指令

加入-posix指令即可,同样要求按照标准。