01. 泛操作
01. 泛操作
常量泛操作
使用
内置常量 - 头文件climits查看符号常量
需要先引入头文件#include<climits>
,然后就可以使用里面的符号常量
符号常量包括最小值和最大值,如需知道宽度,可使用函数sizeof()
符号常量 | 表示对象 | 表示含义 |
---|---|---|
CHAR_BIT | char | 位数 |
CHAT_MAX | char | 最大值 |
CHAR_MIN | char | 最小值 |
SCHAR_MAX | signed char | 最大值 |
SCHAR_MIN | signed char | 最小值 |
UCHAR_MAX | unsigned char | 最大值 |
SHRT_MAX | short | 最大值 |
SHRT_MIN | short | 最小值 |
USHRT_MAX | unsigned short | 最大值 |
INT_MAX | int | 最大值 |
INT_MIN | int | 最小值 |
UINT_MAX | unsigned int | 最大值 |
LONG_MAX | long | 最大值 |
LONG_MIN | long | 最小值 |
ULONG_MAX | unsigned long | 最大值 |
LLONG_MAX | long long | 最大值 |
LLONG_MIN | long long | 最小值 |
ULLONG_MAX | unsigned 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
,禁止修改指向另一变量,允许修改指向的值(即作用对象未pn
,pn
不能改变但*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类的)字符串
- 算术(arithmetic)类型(可以进行运算)
- 复合类型 / 对象数据类型 / 引用类型
- 直接使用类(不需要提前定义类型模板)
- 字符数组
- (字符数组的)字符串
- 类型模板类(需要提前定义类型模板)
- 结构体 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}
- 可省略等号,如
- C语言只能通过大括号初始器(列表初始化)初始化
- 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风格建议下划线
常用的前缀
如:
n
int、str或s
string、b
byte、c
char、p
point(一般组合使用,如pn)、arr或a
array(一般组合使用)大写字母开头留给定义常量
一致性和精度是最重要的
表达式的定义
- 表达式的广义性(C/C++中表达式的定义)
- 任何
值
或有效的值和运算符的组合
都是表达式,例如可x = (y = 1) + 1
、a=b=c=1
- 但注意变量声明不是表达式,for循环这类也不是表达式
- (题外话:C++曾新增了只能在for中出现的
声明语句表达式
,后来又取消了这种特性,修改了for)
- 任何
类型查看
类型长度查看:
sizeof()
,里面可以是具体变量,也可以是变量类型其中字符串常用
strlen()
类型转换(显式和隐式)(与C不同)
类型转换方式
初始化和赋值进行的转换:可缩小可放大,相当于强制类型转换
以
{}
方式初始化:大括号初始化也称列表初始化与普通初始化和赋值相比,其不允许缩窄,例如不允许将浮点型转换为整型
表达式中的转换:同一个表达式中包括两种不同的算术类型时,包含两种转换
自动转换(整型提升):在出现时便会自动转换
会被提升为下列类型中第一个宽度足以存储其取值范围的类型: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最低
传递参数时的转换:由函数原型控制
强制类型转换(显式):有两种方法
- C语言通用方法:不修改变量本身,而是创建一个新的值
- C语言:通用格式
(typeName) value
,例如(float) 1
- C++:通用格式
typeName (value)
,例如float (1)
- C语言:通用格式
- C++新增方法:引入了4个强制类型转换运算符(Stroustrup认为C语言的转换有危险,
static_cast<>
的转换更严格)- 通用格式
static_cast<typeName> (value)
,例如static_cast<long> (n_int)
- (15章才讲)
- (15章才讲)
- (15章才讲)
- 通用格式
- C语言通用方法:不修改变量本身,而是创建一个新的值
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++提供了另一种表示方式:and
、or
、not
(同python)