系统 I/O

示例代码:

#include <iostream>     // 标准库头文件
// #include "myheader.h" // 自己写的头文件 void fun(const char* pInfo, int /* pValue */) //第二个int为设计时候保留接口,在这里没有用到,为后续保留
{
std::cout << pInfo << "\n";
return;
} int main(void)
{
fun("Hello World!", 0);
fun("This is Windows 11", 1);
// return 0; // 返回值类型不标注,默认返回int类型
}
  • iostream :标准库所提供的 IO 接口,用于与用户交互

    • 输入流: cin ;输出流: cout / cerr / clog ,这里的 c 代表 "character"

      输出目标可以重定向,比如输出到单独的文件中,示例代码如下:

      #include <iostream>
      
      int main(void)
      {
      std::cout << "Output from cout \n";
      std::cerr << "Output from cerr \n";
      return 0;
      }

      上面的两个信息,我们可以重定向输出到文件中,使用如下命令:

      g++ -Wall -g basic_io.cpp -o basic_io
      ./basic_io>cout.txt 2>cerr.txt

      然后生成两个新文件:

      > ls
      basic_io.cpp basic_io cerr.txt cout.txt

      然后打开文件夹,就能看到输出内容。

    • 输出流的区别: 1. 输出目标; 2. 是否立即刷新缓冲区

      • 立即刷新缓冲区的作用:使我们即时看到输出的内容
      • cerr 会立即刷新缓冲区
      • clog 不会立即刷新缓冲区
    • 缓冲区与缓冲区刷新: std::flush; std::endl

      显式刷新缓冲区:

      #include <iostream>
      
      int main(void)
      {
      std::cout << "Hello world!\n" << std::flush;
      return 0;
      }

      std::endl 和 std::flush 的区别:前者会刷新缓冲区并换行,后者只刷新缓冲区。

      注意:刷新缓冲区会减缓程序运行速度,需要谨慎使用。

  • 名字空间:用于防止名称冲突

    namespace NameSpace1 {
    void fun()
    {}
    } namespace NameSpace2 {
    void fun()
    {}
    } int main(void)
    { }

    如果我们写的函数在全局中,其实它会默认添加一个全局的名字空间。上述代码在不同的名字空间中定义了两个同名的函数 fun() ,但是可以编译通过。如果都放在全局名字空间中,则会编译出错:

    void fun()
    {} void fun()
    {} int main(void)
    { }
    g++ namespace.cpp -o namespace
    namespace.cpp:16:6: error: redefinition of ‘void fun()’
    16 | void fun()
    | ^~~
    namespace.cpp:13:6: note: ‘void fun()’ previously defined here
    13 | void fun()
    • std 名字空间 :C++标准库的名字空间

    • 访问名字空间中元素的 3 种方式 : 域解析符 :: ; using 语句;名字空间别名

      注意:如下的 using 使用方式是错误的:

      #include <iostream>
      
      namespace NameSpace1 {
      void fun()
      {
      std::cout << "NameSpace1\n";
      }
      } namespace NameSpace2 {
      void fun()
      {
      std::cout << "NameSpace2\n";
      }
      } int main(void)
      {
      using namespace NameSpace1;
      fun();
      using namespace NameSpace2;
      fun(); // error: call of overloaded ‘fun()’ is ambiguous }

      编译出错:

      > g++ namespace.cpp -o namespace
      namespace.cpp: In function ‘int main()’:
      namespace.cpp:22:8: error: call of overloaded ‘fun()’ is ambiguous
      22 | fun();
      | ~~~^~
      namespace.cpp:11:10: note: candidate: ‘void NameSpace2::fun()’
      11 | void fun()
      | ^~~
      namespace.cpp:4:10: note: candidate: ‘void NameSpace1::fun()’
      4 | void fun()
      | ^~~

      为了安全,我们最好还是使用域解析符:

      #include <iostream>
      
      namespace NameSpace1 {
      void fun() { std::cout << "NameSpace1\n"; }
      } // namespace NameSpace1 namespace NameSpace2 {
      void fun() { std::cout << "NameSpace2\n"; }
      } // namespace NameSpace2 void fun() { std::cout << "GlobalNameSpace\n"; } int main(void) {
      // using namespace NameSpace1;
      // fun();
      // using namespace NameSpace2;
      // fun(); // error: call of overloaded ‘fun()’ is ambiguous
      NameSpace1::fun();
      NameSpace2::fun();
      fun(); // global namespace
      }

      这样编译运行就不会出错了。

    • 名字空间与名称改编( name mangling )

      链接的机制:上述的代码中,我们在定义fun() 的时候,分别定义在两个名字空间中,在链接的时候,必须要提供两个不同的连接名称,因为不能用域解析符,此时会涉及到mangling,即名称改编。

      我们将上述的代码编译成目标文件:namespace.o

      g++ namespace.s -c -o namespace.o

      然后使用 nm 命令查看该目标文件中的符号信息

      nm namespace.o
      U _GLOBAL_OFFSET_TABLE_
      00000000000000e0 t _GLOBAL__sub_I__ZN10NameSpace13funEv
      0000000000000048 T _Z3funv
      000000000000008a t _Z41__static_initialization_and_destruction_0ii
      0000000000000000 T _ZN10NameSpace13funEv
      0000000000000024 T _ZN10NameSpace23funEv
      U _ZNSt8ios_base4InitC1Ev
      U _ZNSt8ios_base4InitD1Ev
      U _ZSt4cout
      0000000000000000 b _ZStL8__ioinit
      U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
      U __cxa_atexit
      U __dso_handle
      000000000000006c T main

      de-mangling 操作(即查看原有的名称):

      nm namespace.o | c++filt -t
      U _GLOBAL_OFFSET_TABLE_
      00000000000000e0 unsigned short _GLOBAL__sub_I__ZN10NameSpace13funEv
      0000000000000048 T fun()
      000000000000008a unsigned short __static_initialization_and_destruction_0(int, int)
      0000000000000000 T NameSpace1::fun()
      0000000000000024 T NameSpace2::fun()
      U std::ios_base::Init::Init()
      U std::ios_base::Init::~Init()
      U std::cout
      0000000000000000 bool std::__ioinit
      U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
      U __cxa_atexit
      U __dso_handle
      000000000000006c T main

      注:mangling 和 de-mangling 不会改变 main 函数的名字,因为不会存在同名的 main 函数,所以不需要改变。

      nm 命令显示关于指定 File 中符号的信息,文件可以是对象文件、可执行文件或对象文件库。如果文件没有包含符号信息,nm 命令报告该情况,但不把它解释为出错条件。 nm 命令缺省情况下报告十进制符号表示法下的数字值。

  • C / C++ 系统 IO 比较

    • printf: 使用直观,但容易出错
    • cout: 不容易出错,但书写冗长
    • C++ 20 格式化库:新的解决方案

4. 系统I/O的更多相关文章

  1. 2012高校GIS论坛

    江苏省会议中心 南京·钟山宾馆(2012年4月21-22日) 以"突破与提升"为主题的"2012高校GIS论坛"将于4月在南京举行,由南京大学和工程中心共同承办 ...

  2. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

  3. 数据库优化案例——————某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  4. ABP文档 - 通知系统

    文档目录 本节内容: 简介 发送模式 通知类型 通知数据 通知重要性 关于通知持久化 订阅通知 发布通知 用户通知管理器 实时通知 客户端 通知存储 通知定义 简介 通知用来告知用户系统里特定的事件发 ...

  5. win7安装时,避免产生100m系统保留分区的办法

    在通过光盘或者U盘安装Win7操作系统时,在对新硬盘进行分区时,会自动产生100m的系统保留分区.对于有洁癖的人来说,这个不可见又删不掉的分区是个苦恼.下面介绍通过diskpart消灭保留分区的办法: ...

  6. iOS---iOS10适配iOS当前所有系统的远程推送

    一.iOS推送通知简介 众所周知苹果的推送通知从iOS3开始出现, 每一年都会更新一些新的用法. 譬如iOS7出现的Silent remote notifications(远程静默推送), iOS8出 ...

  7. (系统架构)标准Web系统的架构分层

    标准Web系统的架构分层 1.架构体系分层图 在上图中我们描述了Web系统架构中的组成部分.并且给出了每一层常用的技术组件/服务实现.需要注意以下几点: 系统架构是灵活的,根据需求的不同,不一定每一层 ...

  8. Hyper-V 激活Windows系统重启后黑屏的解决方法 + 激活方法

    异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 服务器相关的知识点:http://www.cnblogs.com/dunitia ...

  9. Beanstalkd一个高性能分布式内存队列系统

    高性能离不开异步,异步离不开队列,内部是Producer-Consumer模型的原理. 设计中的核心概念: job:一个需要异步处理的任务,是beanstalkd中得基本单元,需要放在一个tube中: ...

  10. [APUE]系统数据文件与信息

    一.口令文件 UNIX口令文件包含下表中的各个字段,这些字段包含在 由于历史原因,口令文件是/bin/passwd,而且是一个文本文件,每一行都包括了上表中的七个字段,字段之间用":&quo ...

随机推荐

  1. C语言:输入一串字符串,统计字符串中有多少个数字

    gets函数会在输入完字符后自动补上一个\0,所以用这个特性可以计算出字符串是否结束. 因为数字在字符中对应的ascii码就是0~9,只要遇到小于9的字符就是数字,所以计数器加一 #include&l ...

  2. java学习之旅(day.13)

    常用类 Object类 object类是所有类的父类,所有类直接或间接继承object类 所有类,如果没书写extends显示继承某个类,都默认继承object类 getClass()方法 返回值是c ...

  3. CMD程序_WordCount_博客改

    程序简介 这个程序只能以命令行的方式启动,在启动时要输入相应的命令.程序的功能是对文本文件的字符数,单词数,行数进行统计,将结果输出到默认文件或指定文件. 码云项目链接:WordCount 程序结构 ...

  4. 前端如何对cookie加密

    在前端对 Cookie 进行加密时,你可以使用加密算法对 Cookie 的值进行加密,然后再将加密后的值存储到 Cookie 中.常用的加密算法包括对称加密算法(如 AES)和非对称加密算法(如 RS ...

  5. C# winform GDI+ 五子棋 (一):基本界面和胜负判断

    棋盘和棋子采用GDI+画上去的.棋盘18*18.棋子是用DrawElipse画的,白棋和黑棋分两个List集合存储,方便判断五子连线的情况. 主要说一下,五子连线的思路,把集合按行和按列以及按正斜和反 ...

  6. Linux运维面试总结

    1.Linux系统相关日志 /var/log/message:系统信息日志,包含错误信息 /var/log/secure:系统登录日志 /var/log/maillog:邮件日志 /var/log/c ...

  7. 使用kubadm部署一套k8s学习平台环境

    使用kubeadm部署k8s集群 环境 IP地址 主机名 节点 10.0.0.63 k8s-master1 master1 10.0.0.63 k8s-master2 master2 10.0.0.6 ...

  8. kettle从入门到精通 第三十九课 kettle 增量同步(日级)

    1.上一课我们学习了在数据量大的情况下的分页全量同步示例,本次我们一起学习下kettle 增量全量同步.有些业务场景不需要实时数据,比如统计t-1日的销售业绩情况等.   2.kettle增量全量同步 ...

  9. CompatTelRunner CPU 占用 22% win10 笔记本常常无故风扇狂转

    CompatTelRunner CPU 占用 22% win10 笔记本常常无故风扇狂转 CompatTelRunner.exe is also known as Windows Compatibil ...

  10. 一文了解Spark引擎的优势及应用场景

    Spark引擎诞生的背景 Spark的发展历程可以追溯到2009年,由加州大学伯克利分校的AMPLab研究团队发起.成为Apache软件基金会的孵化项目后,于2012年发布了第一个稳定版本. 以下是S ...