第一章 开始

  • 查看程序运行状态:echo $? 返回上一个命令的状态

    • 程序正常运行,返回0,表示没有错误

    • 返回值-1,打印255;返回值3,打印3;返回值-3,打印打印253

  • endl:这是一个被称为操纵符(manipulator)的特殊值,效果是结束当前行,并将设备关联的缓冲区(buffer)中的内容刷到设备中。

  • UNIX和Mac下键盘输入文件结束符:ctrl+d,Windows下:ctrl+z

  • 库文件:

    • 库文件包含了一系列库函数,一般以二进制文件(链接库)的形式存放
    • 源代码进行预处理编译汇编生成可重定位目标文件后,与库文件进行链接

头文件

  • 背景:不同代码写在不同模块中分别编译,链接时变量或函数需要“有且仅有一次定义,但可以多次声明”,头文件为使用模块的用户提供接口
    • extern进行外部变量的声明(如果对extern变量进行显式初始化则相当于进行了变量的定义)
    • 使用头文件相当于将头文件中每个变量和函数的声明复制到源文件中
    • 不同.cpp将可以include相同的头文件,如果.cpp编译汇编出来的目标文件进行链接,相当于进行多次声明
  • 使用:
    • 可以将函数原型,#define预编译指令,const定义,结构声明,类声明,模板声明,内联函数放在头文件中,其定义放在对应.cpp文件中
    • 头文件不会参与编译
    • 使用时进行include,就相当于预处理器将extern声明插入到源代码
    • 一般情况下,头文件不能放变量或函数的定义(因为可能被多个.cpp文件包含,进而链接时产生多重定义),特殊情况有:
      • 可以定义const变量:const修饰的全局变量作用域只在当前文件中,因此不同文件中的同名const变量是不相同的两个变量,同时const保证了变量值都是常量(static变量虽然作用域只在当前文件中,但是变量值不是常量)
      • 可以定义static变量和static函数
      • 可以定义内联函数:编译器将内联函数进行展开,因此编译期就需要得到内联函数的完整定义
      • 头文件可以定义类(否则编译器无法知道类的成员和偏移,也无法分配内存大小),而且建议头文件名字和类名一致:
        • 对于数据成员,需要等到具体的对象创建时才被定义(分配空间)
        • 对于函数成员,定义类时即被创建:可以将函数成员的实现放在类定义中,此时编译器视这个函数为内联的(不确定);也可以将函数成员的实现单独放在一个.cpp文件中
    • 头文件中的模板:模板实现为会放到头文件中
  • 两种加载头文件的方式:搜索顺序不同,先找到哪个就使用哪个
    • 标准库的头文件使用<>:编译时指定的头文件目录(-I参数指定)、系统环境变量CPLUS_INCLUDE_PATH(C++)或C_INCLUDE_PATH(C)指定的目录、gcc默认目录
      • 标准库的头文件、操作系统相关头文件、安装的特定库的头文件
    • 非标准库的头文件使用"":源文件所在目录、<>头文件搜索目录
  • 防止重复包含
    1
    2
    3
    4
    
    #ifndef HEADFILE_H_ // 判断是否定义过预处理变量HEADFILE_H_(即没有include该头文件)
    #define HEADFILE_H_ // 将一个名字设定为预处理变量(即定义HEADFILE_H_变量);预处理变量的名称需要唯一(无视作用域的规则),且保持全部大写。
    // Definition of Sales_itemclass and related functions goes here
    #endif // 一旦检查预处理变量的结果为真,则执行后续操作,直到遇到#endif
    
    • 高级IDE中可以使用#pragma once来防止头文件的重复包含
  • 参考
  • more reading