main 函数
#include <isotream> // 定义了输入、输出流等
int main(int argc, char *argv[]) { // main 函数
std::cout << "HelloWorld" << std::endl;
return 0;
}
- main 函数作为程序执行入口函数,只能有一个main函数
- 特别注意c++对字符大小写敏感,全部用英文字符
- 使用标准库需要添加对应标准库的头文件
- int <函数返回值类型,返回有符号整形值>
- main(int argc, char *argv[]) 函数名:main,括号中为传入函数的形式参数
- std:: c++标准库的命名空间
- cout 标准库提供的输出流,endl 为输出控制符
- << 输出流重定向运算符
- “HelloWorld” 输出内容
- c++语句都是以 ; 结尾,自动忽略空格
语句注释
void Annotaion() {
// 打印 #
std::cout << "#####" << std::endl;
/*
std::cout << "#####" << std::endl;
这条语句打印 #
*/
}
- c++注释分单行注释和多行注释
- 单行注释:// 单行注释符号
- 多行注释:/**/ 多行注释符号
头文件
#include <isotream> // 头文件
int main() {
std::cout << "HelloWorld" << std::endl;
return 0;
}
- c++在程序编译之前使用预处理器处理源文件
- 预处理器处理以 #include 形式的编译指令, 编译时会自动运行
- 例如 #include, 预处理器将 iostream 文件内容替换或添加到源文件中
- 实际源文件没有被修改,两者会复合成可供编译的复合文件
- c++旧式头文件引用 #include <iostream.h>
- c旧式头文件引用 #include <stdio.h>
- c++新式头文件引用 #include
- c++中对c头文件引用 #include
- c++中对c头文件引用 #include <stdio.h>,两者均可,推荐形式
命名空间
namespace demo { // 命名空间
void Namespace() {
std::cout << "#####" << std::endl;
}
}
- 命名空间尽可能避免不同开发厂商间程序源文件中函数、变量等命名产生冲突
- 声名方法 namespace demo { // 程序代码 }
- 调用方式1 using namespace std;
- 调用方式2 using namespace std::cout
- 调用方式3 std::cout << std::endl;
- c++命名空间的名字一般小写,标准库命名空间为 std
- 如上例子调用方式 demo::Namespace();
变量命名规则
void VariableName() {
int name; // valid
int Name; // valid
int name_; // valid
int name1; // valid
int name_1; // valid
int _name; // valid
int 1name; // invalid
int 1_; // invalid
}
- 变量声明语法: 变量类型(如 int) 变量名
- 只能使用字母字符、数字和下划线(_)
- 数字不能作为变量的第一个字符出现
- c++对大小写严格区分
- 不能将c++所使用的关键字作为变量名称
- 对名称长度没限制,但尽量做到见名知其意
- 常见命名风格:全小写,中间以下划线分割(name_this_var)、小驼峰(nameThisVar)、大驼峰(NameThisVar)
变量定义方式
void DefineVariable() {
int a;
a = 10;
int b = 10;
}
- 两种方式:先声明后初始化(赋值),声明的同时初始化
- c++变量使用必须先声明在使用,否则编译器会报错
变量初始化
int Init() {
int a = 10;
int b;
b = 10;
int c = INT_MAX;
int d = c;
int e(10);
int f{10};
int g = {10};
}
- 声明变量的同时初始化
- 先声明后初始化
- 字面常量值初始化
- 一个变量初始化另一个变量(类型不匹配可能发生隐式数据类型转换)
- c++新增变量初始化语法,声明后直接后边跟小括号、大括号(c++11)初始化方式
- 如果不对函数内部定义的变量初始化(局部变量),该变量的值是不确定的
climits中的符号常量
符号常量 | 表示 |
---|---|
CHAR_BIT | char的位数 |
CHAR_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的最大值 |
有符号整型
#include <iostream>
#include <climits> // 定义了符号常量
void IntegerType() {
short a = SHRT_MAX; // SHRT_MIN
int b = INT_MAX; // INT_MIN
long c = LONG_MAX; // LONG_MIN
long long d = LONG_LONG_MAX; // LONG_LONG_MIN
std::cout << "short : " << a << std::endl;
std::cout << "int : " << b << std::endl;
std::cout << "long : " << c << std::endl;
std::cout << "long long : " << d << std::endl;
std::cout << "sizeof short : " << sizeof(short) << " byte" << std::endl;
std::cout << "sizeof int : " << sizeof(int) << " byte" << std::endl;
std::cout << "sizeof long : " << sizeof(long) << " byte" << std::endl;
std::cout << "sizeof long long : " << sizeof(long long) << " byte" << std::endl;
}
输出结果:
short : 32767
int : 2147483647
long : 2147483647
long long : 9223372036854775807
sizeof short : 2 byte
sizeof int : 4 byte
sizeof long : 4 byte
sizeof long long : 8 byte
- 整形就是没有小数部分的数字,不同类型使用不同的位来存储
- 包括short、int、long、long long,不同类型有不同的存储长度,c++提供了一种灵活的标准
- short至少16位
- int至少和short一样长
- long至少32位,且至少与int一样长
- long long至少64位,且至少与long一样长
- 1GB = 1024MB,1MB = 1024KB,1KB = 1024byte,1byte = 8bit
- 如上例子中获取了这几种类型的长度和最值,实际执行使用平台不同可能会存在差异
- sizeof运算符可得出变量或类型的长度,其中使用变量时,其后边的括号可选,例如(sizeof a;)或(sizeof (a)😉
- 头文件 climits 中定义了类型的长度范围
无符号整型
#include <iostream>
#include <climits>
void UnsignedType() {
unsigned short a = USHRT_MAX;
unsigned int b = UINT_MAX;
unsigned long c = ULONG_MAX;
unsigned long long d = ULONG_LONG_MAX;
unsigned e = UINT_MAX; // unsigned int
std::cout << "unsigned short : " << a << std::endl;
std::cout << "unsigned int : " << b << std::endl;
std::cout << "unsigned long : " << c << std::endl;
std::cout << "unsigned long long : " << d << std::endl;
std::cout << "unsigned int : " << e << std::endl;
std::cout << "sizeof unsigned short : " << sizeof(unsigned short) << " byte" << std::endl;
std::cout << "sizeof unsigned int : " << sizeof(unsigned int) << " byte" << std::endl;
std::cout << "sizeof unsigned long : " << sizeof(unsigned long) << " byte" << std::endl;
std::cout << "sizeof unsigned long long : " << sizeof(unsigned long long) << " byte" << std::endl;
std::cout << "sizeof unsigned int : " << sizeof(unsigned) << " byte" << std::endl;
}
输出结果:
unsigned short : 65535
unsigned int : 4294967295
unsigned long : 4294967295
unsigned long long : 18446744073709551615
unsigned int : 4294967295
sizeof unsigned short : 2 byte
sizeof unsigned int : 4 byte
sizeof unsigned long : 4 byte
sizeof unsigned long long : 8 byte
sizeof unsigned int : 4 byte
- 无符号整型最小值为0,使用 unsigned 关键字修饰类型
- 包括unsigned short、unsigned int、unsigned long、unsigned long long
- 最大值可根据宏定义查看
整型变量溢出
void MaxMin() {
short a = SHRT_MAX;
short b = SHRT_MIN;
int c = INT_MAX;
int d = INT_MIN;
// ...
std::cout << "short max: " << a << " short min: " << b << std::endl;
std::cout << "short max + 1: " << a + 1 << " short min - 1: " << b - 1 << std::endl;
std::cout << "int max: " << c << " int min: " << d << std::endl;
std::cout << "int max + 1: " << c << " int min - 1: " << d << std::endl;
unsigned long e = ULONG_MAX;
std::cout << "unsigned long max: " << e << " unsigned long min: 0 " << std::endl;
std::cout << "unsigned long max + 1: " << e + 1 << " unsigned long min - 1:" << e + 1 - 1 << std::endl;
}
输出结果:
short max: 32767 short min: -32768
short max + 1: 32768 short min - 1: -32769
int max: 2147483647 int min: -2147483648
int max + 1: 2147483647 int min - 1: -2147483648
unsigned long max: 4294967295 unsigned long min: 0
unsigned long max + 1: 0 unsigned long min - 1:4294967295
- 每种类型都有其对应的最值范围,使用时合理选择变量类型切勿超过最值范围
- 如上例子分析可见,最大值溢出后会变成最小值、最小值溢出后会变成最大值
整型字面值
void HexOctDec() {
int a = 15656;
std::cout << "Hex: " << std::hex << a << std::endl;
std::cout << "Oct: " << std::oct << a << std::endl;
std::cout << "Dec: " << std::dec << a << std::endl;
}
输出结果:
Hex: 3d28
Oct: 36450
Dec: 15656
- 整型字面值是显式书写的常量,c++支持以八进制、十进制、十六进制
- 使用 std::cout 输出默认为十进制,输出八进制或十六进制需要添加控制符号
- 十六进制以0x或0X标识,例如 int a = 0x96;,使用字符0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F
- 八进制以0标识,例如 int a = 071;,使用字符0、1、2、3、4、5、6、7
c++确定常量类型
void ConstVarType() {
auto a = 1942;
std::cout << "int: " << (typeid (a) == typeid (int)) << std::endl;
auto b = 1942U;
std::cout << "unsigned int: " << (typeid (b) == typeid (unsigned int)) << std::endl;
auto c = 1942L;
std::cout << "long: " << (typeid (c) == typeid (long)) << std::endl;
auto d = 1942UL;
std::cout << "unsigned long: " << (typeid (d) == typeid (unsigned long)) << std::endl;
auto e = 1942LL;
std::cout << "long long: " << (typeid (e) == typeid (long long)) << std::endl;
auto f = 1942ULL;
std::cout << "unsigned long long: " << (typeid (f) == typeid (unsigned long long)) << std::endl;
auto g = static_cast<short>(1942);
std::cout << "short: " << (typeid (g) == typeid (short)) << std::endl;
auto h = static_cast<unsigned short>(1942);
std::cout << "unsigned short: " << (typeid (h) == typeid (unsigned short)) << std::endl;
auto i = 1942.0;
std::cout << "double: " << (typeid (i) == typeid (double)) << std::endl;
auto j = 1942.0f;
std::cout << "float: " << (typeid (j) == typeid (float)) << std::endl;
}
输出结果:
int: 1
unsigned int: 1
long: 1
unsigned long: 1
long long: 1
unsigned long long: 1
short: 1
unsigned short: 1
double: 1
float: 1
- 整型常量默认为 int(不溢出时)、浮点型常量默认为 double
- 指定常量类型可使用后缀声明
- 如上例子通过不同后缀常量创建不同类型的变量,最终判断创建的变量类型是否为指定的变量类型,输出1表示两边相同
- typeid 运算符用来获取一个表达式的类型信息
- auto在c++11中可用作变量的类型自动推导
char类型
void CharType() {
std::cout <<"char max: " << CHAR_MAX << " char min: " << CHAR_MIN << std::endl;
std::cout <<"unsigned char max: " << UCHAR_MAX << " unsigned char min: " << 0 << std::endl;
char a = 'H';
char b = 'e';
char c = 'l';
char d ='l';
char e = 'o';
std::cout << a << b << c << d << e << std::endl;
char f = 56;
std::cout << "f : " << f << std::endl;
std::cout << "f : " << static_cast<int>(f) << std::endl;
char g;
std::cout << "please input a character: ";
std::cin >> g; // 等待从终端输入字符赋值给变量g
std::cout << "print character: ";
std::cout.put(g); // 打印一个字符
std::cout << std::endl;
}
输出结果:
char max: 127 char min: -128
unsigned char max: 255 unsigned char min: 0
Hello
f : 8
f : 56
please input a character: H
print character: H
- char类型是专为存储字符(如字母和数字)而设计的,最值范围也比较小
- 使用std::cout输出字符会输出对应的ASCII字符集,想输出数字需要强制转换为整型
- static_cast是c++提供的运算符,把一个表达式转换为某种类型,但没有运行时类型检查来保证转换的安全性
- wchar_t(宽字符类型)、c++11新增char16_t和char32_t类型
字符名称 | ASCII符号 | c++代码 | 十进制ASCII码 | 十六进制ASCII码 |
---|---|---|---|---|
换行符 | NL(LF) | \n | 10 | 0XA |
水平制表符 | HT | \t | 9 | 0X9 |
垂直制表符 | VT | \v | 11 | 0XB |
退格 | BS | \b | 8 | 0X8 |
回车 | CR | \r | 13 | 0XD |
振铃 | BEL | \a | 7 | 0X7 |
反斜杠 | |\|92 | 0X5C | ||
问号 | ? | ? | 63 | 0X3F |
单引号 | ’ | ’ | 39 | 0X27 |
双引号 | " | " | 34 | 0X22 |
bool类型
void BoolType() {
bool a = true;
bool b = false;
bool c = 10;
bool d = 0;
int e = 10;
bool f = e;
int g = f;
std::cout << "a : " << a << std::endl;
std::cout << "b : " << b << std::endl;
std::cout << "c : " << c << std::endl;
std::cout << "d : " << d << std::endl;
std::cout << "e : " << e << std::endl;
std::cout << "f : " << f << std::endl;
std::cout << "g : " << g << std::endl;
}
输出结果:
a : 1
b : 0
c : 1
d : 0
e : 10
f : 1
g : 1
- 布尔变量的值只有 true、false
- 字面值true和false都可以被转换为int类型,true是1,false是0
- 任何数字值或指针值都可以被转换(不用强制显示转换)为bool值,非零值为true,零值为false
浮点类型
void FloatType() {
float a = 1.0;
double b = 1E-4;
long double c = 1.0;
std::cout << "a: " << a << "\tb: " << b << "\tc: " << c << std::endl;
std::cout << "sizeof float: " << sizeof (float) << std::endl;
std::cout << "sizeof double: " << sizeof (double) << std::endl;
std::cout << "sizeof long double: " << sizeof (long double) << std::endl;
std::cout << "double max: " << __DBL_MAX__ << "\tdouble min: " << __DBL_MIN__ << std::endl;
}
输出结果:
a: 1 b: 0.0001 c: 1
sizeof float: 4
sizeof double: 8
sizeof long double: 16
double max: 1.79769e+308 double min: 2.22507e-308
- 浮点数能够表示带小数部分的数字
- 三种类型定义,float、double和long double,小数精确度依次提高
- 可以使用科学计数法初始化
- 浮点数可以表示整数
- 通常浮点数具有精度损失,运算速度相对整数慢
类型转换
void ConvertType() {
int a = 10;
long long b = a;
double c = 4.5;
int d = c;
int *e = &a;
long *f = reinterpret_cast<long *>(e); // 强制类型转换
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
std::cout << "c: " << c << std::endl;
std::cout << "d: " << d << std::endl;
std::cout << "*e: " << *e << std::endl;
std::cout << "*f: " << *f << std::endl;
}
输出结果:
a: 10
b: 10
c: 4.5
d: 4
*e: 10
*f: 10
- 两种转换方式:隐式转换和显式转换(强制类型转换)
- 隐式转换:将长度小的类型赋值给长度大的类型时会隐式转换为长度大的类型
- 显式转换:将类型强制转换并赋值给某种类型
- 浮点数直接赋值给整型将丢失小数部分
- 尽量避免设计的程序中使用显式类型转换
- C++引入了四种功能不同的强制类型转换运算符:static_cast、reinterpret_cast、const_cast 和 dynamic_cast
- static_cast 用于进行比较低风险的转换,如整型和浮点型、字符型之间的互相转换,如果对象所属的类重载了强制类型转换运算符T(如 T 是 int、int* 或其他类型名),则 static_cast 也能用来进行对象到 T 类型的转换,static_cast 不能用于在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换,因为这些属于风险比较高的转换
- reinterpret_cast 用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换,转换时,执行的是逐个比特复制的操作,这种转换提供了很强的灵活性,但转换的安全性只能由程序员的细心来保证了,例如,程序员执意要把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的
- const_cast 运算符仅用于进行去除 const 属性的转换,它也是四个强制类型转换运算符中唯一能够去除 const 属性的运算符,将 const 引用转换为同类型的非 const 引用,将 const 指针转换为同类型的非 const 指针时可以使用 const_cast 运算符。
- 用 reinterpret_cast 可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针,但是这种转换不检查安全性,即不检查转换后的指针是否确实指向一个派生类对象,dynamic_cast专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性,对于不安全的指针转换,转换结果返回 NULL 指针,dynamic_cast 是通过 运行时类型检查 来保证安全性的,dynamic_cast 不能用于将非多态基类的指针或引用强制转换为派生类的指针或引用——这种转换没法保证安全性,用 reinterpret_cast
数组
void ArrayType() { // 一维数组
int arr[10]; // 声明数组未初始化,值是随机值
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << arr[i] << " ";
std::cout << std::endl;
arr[0] = 10; // 局部元素赋值,索引访问数组元素
arr[2] = 20;
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << arr[i] << " ";
std::cout << std::endl;
for (int i = 0; i < 10; ++i) // 数组每个元素赋值
arr[i] = i;
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << arr[i] << " ";
std::cout << std::endl;
int *p = arr; // 指针指向数组,数组名就是数组的首地址指针
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << p[i] << " ";
std::cout << std::endl;
// 数组初始化方式
int a[4] = {1}; // 初始化第一个元素,其余元素默认为 0
for (int i = 0; i < 4; ++i) // 循环打印数组元素
std::cout << a[i] << " ";
std::cout << std::endl;
int b[2] = {1, 2}; // 初始化所有元素
for (int i = 0; i < 2; ++i) // 循环打印数组元素
std::cout << b[i] << " ";
std::cout << std::endl;
int c[] = {1, 2, 3}; // 全部元素初始化并自动推导数组元素个数
for (int i = 0; i < 3; ++i) // 循环打印数组元素
std::cout << c[i] << " ";
std::cout << std::endl;
int d[2]{0, 2}; // c++11的初始化列表
for (int i = 0; i < 2; ++i) // 循环打印数组元素
std::cout << d[i] << " ";
std::cout << std::endl;
int e[10] = {}; // 所有元素初始化为零
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << e[i] << " ";
std::cout << std::endl;
int f[10]{}; // 所有元素初始化为零
for (int i = 0; i < 10; ++i) // 循环打印数组元素
std::cout << f[i] << " ";
std::cout << std::endl;
}
输出结果:
6684064 0 14755456 0 6684240 0 16 0 8 0
10 0 20 0 6684240 0 16 0 8 0
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
1 0 0 0
1 2
1 2 3
0 2
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
- 数组是一种数据格式,存储多个相同类型的值
- 声明:值类型、数组名和数组中的元素个数(type arr[size])
- 数组访问可通过下标索引访问(arr[i])或指向数组的指针访问
- 数组可容纳的元素数量一旦确定就不能改变,访问数组中的元素时一定要注意索引是否越界(超出数组长度)
- c++中索引都以 0 开始,即数组中的第一个元素为 arr[0]
- 一维数组初始化方式如上例子