跳至主要內容

01. 泛操作

LincZero大约 8 分钟

01. 泛操作

常量泛操作

使用

内置常量 - 头文件climits查看符号常量

需要先引入头文件#include<climits>,然后就可以使用里面的符号常量

符号常量包括最小值和最大值,如需知道宽度,可使用函数sizeof()

符号常量表示对象表示含义
CHAR_BITchar位数
CHAT_MAXchar最大值
CHAR_MINchar最小值
SCHAR_MAXsigned char最大值
SCHAR_MINsigned char最小值
UCHAR_MAXunsigned char最大值
SHRT_MAXshort最大值
SHRT_MINshort最小值
USHRT_MAXunsigned short最大值
INT_MAXint最大值
INT_MINint最小值
UINT_MAXunsigned int最大值
LONG_MAXlong最大值
LONG_MINlong最小值
ULONG_MAXunsigned long最大值
LLONG_MAXlong long最大值
LLONG_MINlong long最小值
ULLONG_MAXunsigned long long最大值

定义常量 - 预处理器方式和const限定符(与C不同)

  • 使用
    • #define,预处理方式。使用举例#define INT_MAX 32767
    • const,限定符方式。通用格式const type name = value,使用举例:const int Months = 12
      • 注意!const必须在声明时提供常量值,否则无法通过后期赋(修改)值
      • const是C++的新方法,更好用:能指定类型、能定义更复杂的类型、可以指定作用域
    • typedef,类型别名方式
    • enum,可以通过枚举类型来定义一些字符常量名
  • 预处理方式:#define#include一样,使用预处理器编译指令
    • #define,是在程序中查找常量名(完全匹配才算),并全部替换为常量名所表示的值
    • #include,是在头部插入头文件
  • 补充:头文件climits所定义的符号常量也是使用该方法
  • const与指针
    • 有两种用法,如下:
    • const int * pn = &n,禁止修改指向的值,允许修改指向另一变量(即作用对象为*pn*pn不能改变但pn可以)
    • int * const pn = &n,禁止修改指向另一变量,允许修改指向的值(即作用对象未pnpn不能改变但*pn可以)

变量泛操作(内置)

简概

类型(与C不同)

C++的类型

  • 基本类型 / 基本数据类型
    • 算术(arithmetic)类型(可以进行运算)
      • 整型(无小数点数)
        • 符号整型:signed char、short、int、long
        • 无符号整型:上面的无符号版本
        • (C++新增:long long、bool、char、wchar_t、char16_t、char32_t)
      • 浮点型(有小数点数)
        • float、double、long double
    • (string类的)字符串
  • 复合类型 / 对象数据类型 / 引用类型
    • 直接使用类(不需要提前定义类型模板)
      • 字符数组
      • (字符数组的)字符串
    • 类型模板类(需要提前定义类型模板)
      • 结构体 struct(类似于类)
      • 共用体 union(每次只能使用其中一种类型,用于节约空间)
      • 枚举 enum(可以用来定义常量)

使用

初始化和声明(与C不同)

C++初始化方式

  • 经典C语言方式
    • int n_int = 1,可以定义多个int a,b,c
  • 大括号初始化器,如int n_int = {1}
    • C语言只能通过大括号初始器(列表初始化)初始化类变量,C++将其作为一种通用初始化方式,并且其新增了一些功能:
      • 可省略等号,如int n_int {1}
      • 可省略大括号里的值(初始化为0),如int n_int {}(优点:能更好防范类型转换错误)
      • 禁止缩窄转换,如不能int n_int {1.0}
  • auto类型(C++新增,类似于TypeScript中的any类型),用法和经典C语言方式相同
    • 编译器会根据初始值的类型判断变量的类型并设置,例如auto lf_bar = 1.5L
    • 适用用处:C++11让程序员将主要精力放在设计而不是细节上
      • 比如用auto pc = &pa;代替const double *(*(*pd)[3])(const double *, int) = &pa(一个函数指针)

变量名选择

  • 合法规则

    • 由字母数字下划线组成
    • 非数字开头
    • 区分大小写
    • 不能使用关键字
    • 两个下划线打头,或下划线+大写字母打头的名称被保留给实现使用,一个下划线打头的名称被保留给实现,用作全局标识符
  • C语言只保证名称前63个字符有意义,C++对于名称长度没有限制

  • 变量名建议规范

    • 小驼峰/下划线/大驼峰都行,C风格建议下划线

    • 常用的前缀

      如:nint、str或sstring、bbyte、cchar、ppoint(一般组合使用,如pn)、arr或aarray(一般组合使用)

    • 大写字母开头留给定义常量

    • 一致性和精度是最重要的

表达式的定义

  • 表达式的广义性(C/C++中表达式的定义)
    • 任何有效的值和运算符的组合都是表达式,例如可x = (y = 1) + 1a=b=c=1
    • 但注意变量声明不是表达式,for循环这类也不是表达式
    • (题外话:C++曾新增了只能在for中出现的声明语句表达式,后来又取消了这种特性,修改了for)

类型查看

  • 类型长度查看sizeof(),里面可以是具体变量,也可以是变量类型

    其中字符串常用strlen()

类型转换(显式和隐式)(与C不同)

类型转换方式

  1. 初始化和赋值进行的转换:可缩小可放大,相当于强制类型转换

  2. {}方式初始化:大括号初始化也称列表初始化

    与普通初始化和赋值相比,其不允许缩窄,例如不允许将浮点型转换为整型

  3. 表达式中的转换:同一个表达式中包括两种不同的算术类型时,包含两种转换

    • 自动转换(整型提升):在出现时便会自动转换

      会被提升为下列类型中第一个宽度足以存储其取值范围的类型:int、unsigned int、long、unsigned long

      如:(int是计算机最自然的类型)

      • bool、char、unsigned char、signed char、short换转换成int
      • 范围(short)<范围(int),unsigned short转换为int
      • 范围(short)=范围(int),unsigned short转换为unsigned int
    • 不同类型进行运算时:较小的类型被转换为较大的类型,简单来说:

      有符号整型long long>long>int>short>signed char,无符号相同,char=signed char=unsigned char,bool最低

  4. 传递参数时的转换:由函数原型控制

  5. 强制类型转换(显式):有两种方法

    • C语言通用方法:不修改变量本身,而是创建一个新的值
      • C语言:通用格式(typeName) value,例如(float) 1
      • C++:通用格式typeName (value),例如float (1)
    • C++新增方法:引入了4个强制类型转换运算符(Stroustrup认为C语言的转换有危险,static_cast<>的转换更严格)
      • 通用格式static_cast<typeName> (value),例如static_cast<long> (n_int)
      • (15章才讲)
      • (15章才讲)
      • (15章才讲)

bool补充

  • 所有数字值或指针值都可以被隐式转换(不用显式强制转换)为bool值
  • 任何非零值转换为true,零转换为false

类型别名

有两种方法

  • 常量定义方式:如#define BYTE char(不建议)
  • typedef方式:如typedef char byte(建议)
  • 比较
    • 后者能处理更复杂的类型别名,不会出现以下情况:
    • 比如#define FP float *; FP pa, pb;会变成float *pa, pb而非float *pa, *pb

符号

  • 算术运算符:从左到右,乘除>加减,()提升优先级

  • 递增运算符和递减运算符:++--

    • 这里注意一下两种变体:前缀格式和后缀格式

      • i++/i--后缀格式:先运算当前值表达式,再运算自增自减

        例:a=0; b=(a++)+1,等同a=0; b=a+1; a++,结果a=1; b=1

      • ++i/--i前缀格式:先运算自增自减,再运算当前值表达式

        例:a=0; b=(++a)+1,等同a=0; a++; b=a+1,结果a=1; b=2

    • 可以用副作用和顺序点的概念来理解

      • 程序只保证程序执行到下个语句之前对所有副作用进行评估,而不保证计算完子表达式还是整个表达式计算完后才评估副作用
      • 故应避免这样的写法:y = (4+x++) + (6+x++)
    • 细微的性能区别

      • 如果表达式的值未被使用,而只有副作用,则使用两种版本效果一样,但性能有细微区别
      • 对数来说差距很少,但允许对类使用前缀函数和后缀函数,差距会变大
      • 后缀版本首先复制一个副本,将其加1,再返回复制的副本。即前缀版本的效率更高
  • 关系运算符:>>===<=<!=

  • 组合赋值运算符:+=-=*=/=%=

  • 逗号运算符:,

    语句块允许把多条语句放到按C++句法只能放一条语句的地方,逗号运算符同样可以做到相同的工作。最常用的用途是讲多个表达式放到一个for循环表达式中

  • 逻辑运算符:&&||!,C++提供了另一种表示方式:andornot(同python)