从今天起开始C++的学习,为以后学习QT、OpenCV铺路。

本篇是C++教程中C部分的总集,为本专栏里所有 1.x部分的集合,嫌一篇篇看麻烦的直接看本篇好了。

开发环境搭建:Visual Studio 2019 C++开发环境搭建

推荐教程视频:https://www.bilibili.com/video/BV1et411b73Z?from=search&seid=4205594350351753444

已投币三连,非常好的视频教程,感谢up主的奉献。

一、代码的注释

代码注释常用于标注代码功能、记录作者和版本修改信息,方便阅读查看。

// 单行注释/* ......多行注释......*/#include <iostream>
using namespace std;/*多行注释main 主函数*/
int main() {cout << "Hello World!!" << endl;  // 单行注释,打印输出Hello world!!system("pause");return 0;
}

cout:c out,打印输出,相当于 printf。

cin:c in,检测输入,相当于 scanf。

endl:end line,换行结束,相当于键盘敲回车。

system("pause");:让程序暂停,按任意键继续。

二、变量

变量,字面意思,可以被改变的数据。而实际是给计算机的一段内存空间起名,方便操作这段内存的数据。

变量如果需要被使用,需要先声明变量。声明变量的格式:

数据类型 变量名 = 初始值;

#include <iostream>
using namespace std;int main() {int i = 100;cout << "Hello World!!" << endl;cout << "i = " << i << endl;system("pause");return 0;
}

三、常量

可以被修改的数据叫做变量,不可被修改的数据叫常量。

C++定义常量有两种方法:

(1)#define宏常量:#define    常量名    常量值

通常在代码文件的上方声明。

#define  常量名  常量值#define  Year  2020
#define  Name  "XiaoMing"

(2)const修饰变量:const    数据类型    常量名    =    常量值

const  数据类型  常量名 = 常量值const  int  year = 2020;

常量被修改,编译器会报错。

四、关键字

是C++中预先保留的单词(标识符)。

注意:给变量或者常量起名称时,不要和关键字重复,会有语法歧义。

五、标识符(变量、常量)命名规则

(1)标识符不能是关键字

(2)标识符只能由 数字、字母、下划线 组成。

(3)标识符的第一个字符必须是 字母或者下划线。

(4)标识符中字母区分大小写

可以是 inta,但不能是 int。

year2020、Status、_a、Student_66 这些都符合命名规则,但 2class、618_Day 这样以 数字开头的不行。

Age 和 age 代表的变量并不是同一个,是两个独立且互不相关的变量。

标识符命名尽量简介直观,方便自己和他人阅读。

六、数据类型

(1)整形

整型数据类型的区别,主要是占用空间的不同,从而导致取值范围不同,有大有小。

int最为常用。

数据类型 占用空间 取值范围
short(短整型) 2个字节(Byte) (-2^15 ~ 2^15-1)
int(整形) 四个字节 (-2^31 ~ 2^31-1)
long(长整型) windows为4个字节、32位linux为4个字节、64位linux为8个字节 (-2^31 ~ 2^31-1)
long long(长长整型) 8个字节 (-2^63 ~ 2^63-1)

(2)实型(浮点型)

表示小数。区别在于表示的有效数字范围不同。

数据类型 占用空间 有效数字范围
float(单精度浮点) 4字节 7位有效数字
double(双精度浮点) 8字节 15~16位有效数字

注意:有效数字范围,并不是指小数点后的数,而是整个浮点的数的数量。例如 3.14,有效数字为3。

默认的 cout  << 输出浮点类型,会显示6位有效数字。

(3)字符型

显示单个字符。c/c++中,字符型变量只占用一个字节。

字符型变量不是将字符放入内存中,而是将对应的ASCII编码放入内存。

char ch = 'a';

ASCII 编码对照表:https://baike.baidu.com/item/ASCII/309296?fr=aladdin

(4)转义字符

表示一些不能显示出来的ASCII字符。

对照表:https://www.cnblogs.com/lsqbk/p/10259044.html

(5)字符串类型

表示一串字符。

C风格字符串:

char str1[] = "123abc";

C++风格字符串:

string str1 = "123abc";    // 需要包含头文件 #include <string>

(6)布尔类型

代表真或假的值。

bool的值只有两个:

true - 真,1

false - 假,0

(7)数据的输入

用于从键盘获取数据。

语法:cin >> 变量

(8)sizeof 统计内存大小

sizeof关键字,可以统计数据类型所占内存大小。

sizeof(数据类型/变量)
#include <iostream>
using namespace std;int main() {cout << "short\t\t占用空间:" << sizeof(short) << endl;cout << "int\t\t占用空间:" << sizeof(int) << endl;cout << "long\t\t占用空间:" << sizeof(long) << endl;cout << "long long\t占用空间:" << sizeof(long long) << endl;cout << "float\t\t占用空间:" << sizeof(float) << endl;cout << "double\t\t占用空间:" << sizeof(double) << endl;cout << "char\t\t占用空间:" << sizeof(char) << endl;cout << "bool\t\t占用空间:" << sizeof(bool) << endl;system("pause");return 0;
}
---------------------------------------------------------------------------
short           占用空间:2
int             占用空间:4
long            占用空间:4
long long       占用空间:8
float           占用空间:4
double          占用空间:8
char            占用空间:1
bool            占用空间:1
请按任意键继续. . .

sizeof 和 strlen 区别:sizeof 和 strlen 区别

七、运算符

运算符用于执行代码的运算。

运算符分类:

运算符类型 作用
算术运算符 处理四则运算
赋值运算符 将表达式的值赋给变量
比较运算符 表达式的比较,并返回一个真值或假值
逻辑运算符 根据表达式的值返回真值或假值

(1)算术运算符

处理四则运算。

运算符 术语 示例 结果
+ 正号 +5 5
- 负号 -5 5
+ 2 + 3 5
- 5 - 3 2
* 2 * 3 6
/ 6 / 3 2
% 取模(取余) 10 % 3 1
++ 前置递增 a=2; b=++a; a = 3; b = 3;
-- 前置递减 a=2; b=--a; a = 1; b = 1;
++ 后置递增 a=2; b=a++; a = 3; b = 2;
-- 后置递减 a=2; b=a--; a = 1; b = 2;

(2)赋值运算符

将表达式的值赋给变量。

运算符 术语 示例 结果
= 赋值(等于) a=2; a=2;
+= 加等于 a=2; a+=2; a=4;
-= 减等于 a=2; a-=2; a=0;
*= 乘等于 a=2; a*=3; a=6;
/= 除等于 a=6; a/=3; a=2;
%= 模等于 a=10; a%=3; a=1;

(3)比较运算符

表达式的比较,并返回一个真值或假值。

运算符 术语 示例 结果
== 相等于 5 == 2 0
!= 不等于 5 != 2 1
< 小于 5 < 2 0
> 大于 5 > 2 1
<= 小于等于 5 <= 2 0
>= 大于等于 5 >= 2 1

注意:= 和 == 的使用区别。

(4)逻辑运算符

根据表达式的值返回真值或假值

运算符 术语 示例 结果
! !a 如果 a为假,则 !a为真。反之则反
&& 逻辑与 a && b a,b全为1时, a && b = 1。a,b任意一个为0, a && b = 0。
|| 逻辑或 a || b a,b全为0时, a || b = 0。a,b任意一个为1, a || b = 1。

注意:& 和 &&、| 和 || 的使用区别。与 与逻辑与,或 与 逻辑或。

八、程序流程结构

c/c++支持最基本的三种程序运行结构顺序结构、选择结构、循环结构

顺序结构:程序按顺序执行,不发生跳转。

选择结构:依据条件是否满足,有选择的执行相应功能。

循环结构:依据条件是否满足,循环多次执行某段代码。

(1)选择结构

1. 使用 if语句,语法为:

if (条件) {/* 满足条件后,可执行括号中内容 */// ...
}
if (条件1) {/* 满足条件1后,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
else if (条件2) {/* 如果条件1不满足,而条件2满足,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
else if (条件3) {/* 如果条件1、条件2均不满足,而条件3满足,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
...
...
...
if (条件1) {/* 满足条件1后,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
else if (条件2) {/* 如果条件1不满足,而条件2满足,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
else if (条件3) {/* 如果条件1、条件2均不满足,而条件3满足,执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
...
...
...
else {/* 如果条件1、条件2、条件3...均不满足,则执行本括号中程序 */// .../* 执行完程序后,结束整个if结构 */
}
int main() {int a = 0;if (a < 0) {cout << "a小于0" << endl;}else if (a > 0) {cout << "a大于0" << endl;}else {cout << "a等于0" << endl;}system("pause");return 0;
}
---------------------------------------------------
a等于0
请按任意键继续. . .

if支持多重嵌套。

2. 三目运算符

三目运算符可实现简单的判断。语法:

表达式1 ? 表达式2 : 表达式3
// 如果表达式1为真,则执行表达式2,并返回表达式2的结果。
// 如果表达式1为假,则执行表达式3,并返回表达式3的结果。
int main() {int a = 10;a > 0 ? cout << "a大于0" << endl : cout << "a小于0" << endl;system("pause");return 0;
}
------------------------------------------------------------------
a大于0
请按任意键继续. . .

3. switch语句。执行多条件分支语句。语法:

switch (表达式) {case 结果1: 执行代码段; break;case 结果2: 执行代码段; break;case 结果3: 执行代码段; break;.........defaule: 执行代码段; break;
}
 int usr=0;cout << "请输入1、2、3其中一个数字" << endl;cin >> usr;switch (usr){case 1:cout << "输入了1" << endl; break;case 2:cout << "输入了2" << endl; break;case 3:cout << "输入了3" << endl; break;default:cout << "不在规定范围内输入" << endl; break;}
--------------------------------------------------------------
请输入1、2、3其中一个数字
3
输入了3
请按任意键继续. . .

注意:别少写break,少写break代码会继续向下执行。直到再次遇到break,才会结束整个switch。

(2)循环结构

1. while循环语句。语法:

while (条件) {/* 满足条件后,执行本括号中程序 */// .../* 执行完程序后,接着判断条件。如满足,继续循环执行本括号程序;如不满足,结束while循环 */
}

2. do while循环语句。语法:

do {// 先执行一次本括号程序// .../* 执行完程序后,判断条件。如满足,继续循环执行本括号程序;如不满足,结束while循环 */
}while (条件)

3. for循环语句。满足循环条件,执行循环语句。语法:

for (表达式1; 表达式2; 表达式3)
{循环语句
}for (初始化语句; 循环条件; 自增或自减)
{循环语句
}
 int i, j;for (i = 0; i < 5; i++){for (j = 0; j < 10; j++){cout << "j ";}cout << "i" << endl;}
-------------------------------------------
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
请按任意键继续. . .

(3)跳转语句

break语句:用于跳出选择结构或循环结构。

(注意:break只会跳出距离它最近的for、while这些循环语句,跟if没有关系)

作用:

出现在switch语句中,作用是终止case并跳出switch。

出现在循环语句中,作用是跳出当前的循环语句。

出现在嵌套循环语句中,跳出最近的内层循环语句。

 int usr=0;cout << "请输入1、2、3其中一个数字" << endl;cin >> usr;switch (usr){case 1:cout << "输入了1" << endl; //break;case 2:cout << "输入了2" << endl; //break;case 3:cout << "输入了3" << endl; //break;default:cout << "不在规定范围内输入" << endl; //break;}
---------------------------------------------------------------
请输入1、2、3其中一个数字
2
输入了2
输入了3
不在规定范围内输入
请按任意键继续. . .
 int i, j;for (i = 0; i < 5; i++){for (j = 0; j < 10; j++){if (j >= 5)break;cout << "j ";}cout << "i" << endl;}
---------------------------------------------------------
j j j j j i
j j j j j i
j j j j j i
j j j j j i
j j j j j i
请按任意键继续. . .
 int i, j;for (i = 0; i < 5; i++){for (j = 0; j < 10; j++){cout << "j ";}cout << "i" << endl;break;}
------------------------------------------------------
j j j j j j j j j j i
请按任意键继续. . .

continue语句:循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环。

 int i, j;for (i = 0; i < 5; i++){for (j = 0; j < 10; j++){if (j == 5 || j == 8){continue;}cout << j;}cout << "i" << endl;}
--------------------------------------------------------
01234679i
01234679i
01234679i
01234679i
01234679i
请按任意键继续. . .

goto语句:可以无条件跳转语句。

(注意:少用,goto不利于梳理代码逻辑)

 cout << "执行代码段1" << endl;goto CODE_1;cout << "执行代码段2" << endl;cout << "执行代码段3" << endl;CODE_1:cout << "执行代码段4" << endl;
---------------------------------------------------------
执行代码段1
执行代码段4
请按任意键继续. . .

九、数组

数组:一个里面存放了相同类型数据元素的集合。

特点:每个数组中的元素都是相同的数据类型;数组是由连续的内存位置组成的。

注意:数组的下标是从0开始索引。

(1.1)一维数组

一维数组的三种定义方式:

数据类型 数组名[ 数组长度 ];
数据类型 数组名[ 数组长度 ] = { 值1, 值2 ...};
数据类型 数组名[ ] = { 值1, 值2 ...};int str1[5];
int str1[5] = { -2, -1, 0, 1, 2};
int str1[] = { -2, -1, 0, 1, 2};
 int i=0;int str1[5];str1[0] = -2;str1[1] = -1;str1[2] = 0;str1[3] = 1;str1[4] = 2;for (i = 0; i <5; i++){cout << str1[i] << " ";}cout << endl;
----------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .
 int i=0;int str1[5] = { -2, -1, 0, 1, 2 };for (i = 0; i <5; i++){cout << str1[i] << " ";}cout << endl;
-----------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .
 int i=0;int str1[] = { -2, -1, 0, 1, 2 };for (i = 0; i <5; i++){cout << str1[i] << " ";}cout << endl;
-------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .

(1.2)一维数组数组名

一维数组名称的用途:

1.可以统计整个数组在内存中的长度。

2.可以获取数组在内存中的首地址。

 int i=0;int str1[5] = { -2, -1, 0, 1, 2 };for (i = 0; i <5; i++){cout << str1[i] << " ";}cout << endl;cout << "str1[]整个数组占用的空间:" << sizeof(str1) << endl;cout << "str1[0]元素占用的空间:" << sizeof(str1[0]) << endl;cout << "str1[]数组中元素个数:" << sizeof(str1) / sizeof(str1[0]) << endl;cout << "str1[]数组的内存首地址:" << str1 << endl;cout << "str1[0]元素的内存首地址:" << &str1[0] << endl;cout << "str1[1]元素的内存首地址:" << &str1[1] << endl;
----------------------------------------------------------------------------------------
-2 -1 0 1 2
str1[]整个数组占用的空间:20
str1[0]元素占用的空间:4
str1[]数组中元素个数:5
str1[]数组的内存首地址:00D8FA64
str1[0]元素的内存首地址:00D8FA64
str1[1]元素的内存首地址:00D8FA68
请按任意键继续. . .

(1.3)一维数组常用算法

寻找最大值:

 int i=0;int str1[5] = { -2, -1, 0, 1, 2 };int start = 0;int end = sizeof(str1) / sizeof(str1[0]);int xtemp = 0;for (i = 0; i < end; i++){if (str1[i] > str1[xtemp]){xtemp = i;}}for (i = 0; i < 5; i++){cout << str1[i] << " ";}cout << endl;cout << "str1[]数组中元素个数:" << end << endl;cout << "str1[]数组中第几个元素为最大值:" << xtemp + 1 << endl;cout << "最大值为:" << str1[xtemp] << endl;
--------------------------------------------------------------------------
-2 -1 0 1 2
str1[]数组中元素个数:5
str1[]数组中第几个元素为最大值:5
最大值为:2
请按任意键继续. . .

逆置(整个数组首位互换):

 int str1[5] = { -2, -1, 0, 1, 2 };int start = 0;int end = sizeof(str1) / sizeof(str1[0]) - 1;int xtemp = 0;for (i = 0; i < 5; i++){cout << str1[i] << " ";}cout << endl;while (start < end){xtemp = str1[start];str1[start] = str1[end];str1[end] = xtemp;start++;end--;}for (i = 0; i < 5; i++){cout << str1[i] << " ";}cout << endl;
--------------------------------------------------------------
-2 -1 0 1 2
2 1 0 -1 -2
请按任意键继续. . .

冒泡排序:

 int i=0,j=0;int str1[5] = { 8, 2, 5, 4, 6 };int start = 0;int end = sizeof(str1) / sizeof(str1[0]) - 1;int xtemp = 0;cout << "数组原始值:";for (i = 0; i < 5; i++){cout << str1[i] << " ";}cout << endl;for (i = end; i > 0; i--){for (j = 0; j < i; j++){if (str1[j] > str1[j + 1]){xtemp = str1[j];str1[j] = str1[j + 1];str1[j + 1] = xtemp;}}}cout << "冒泡排序后:";for (i = 0; i < 5; i++){cout << str1[i] << " ";}cout << endl;
----------------------------------------------------------------------
数组原始值:8 2 5 4 6
冒泡排序后:2 4 5 6 8
请按任意键继续. . .

(2.1)二维数组

二维数组的四种定义方式:

数据类型 数组名[ 行数 ][ 列数 ];
数据类型 数组名[ 行数 ][ 列数 ] = { { 值1, 值2 ...}, { 值11, 值12 ...},  ... };
数据类型 数组名[ 行数 ][ 列数 ] = { 值1, 值2, 值3, 值4 ...};
数据类型 数组名[  ][ 列数 ] = { 值1, 值2, 值3, 值4 ...};int str1[2][3];
int str1[2][3] = { { -2, -1, 0}, { 1, 2, 3} };
int str1[2][3] = { -2, -1, 0, 1, 2, 3};
int str1[][3] = { -2, -1, 0, 1, 2, 3};
 int i=0,j=0;int str1[2][3] = { { -2, -1, 0}, { 1, 2, 3} };//int str1[2][3] = { -2, -1, 0, 1, 2, 3 };//int str1[][3] = { -2, -1, 0, 1, 2, 3 };for (i = 0; i < 2; i++){for (j = 0; j < 3; j++){cout << str1[i][j] << " ";}cout << endl;}
----------------------------------------------------------------
-2 -1 0
1 2 3
请按任意键继续. . .

(2.2)二维数组数组名

二维数组名称的用途:

1.统计二维数组所占内存空间。

2.获取二维数组在内存中的首地址。

 int i = 0,j = 0;int str1[2][3] = { { -2, -1, 0},{ 1, 2, 3}};for (i = 0; i < 2; i++){for (j = 0; j < 3; j++){cout << str1[i][j] << " ";}cout << endl;}cout << "str1[][]二维数组占用的空间:" << sizeof(str1) << endl;cout << "str1[][]第一行占用的空间:" << sizeof(str1[0]) << endl;cout << "str1[0][0]元素占用的空间:" << sizeof(str1[0][0]) << endl;cout << endl;cout << "str1[][]二维数组的行数:" << sizeof(str1) / sizeof(str1[0]) << endl;cout << "str1[][]二维数组的列数:" << sizeof(str1[0]) / sizeof(str1[0][0]) << endl;cout << "str1[][]二维数组中所有元素个数:" << sizeof(str1) / sizeof(str1[0][0]) << endl;cout << endl;cout << "str1[][]二维数组的内存首地址:" << str1 << endl;cout << "str1[0][0]第一行行首的内存首地址:" << &str1[0][0] << endl;cout << "str1[0][1]元素的内存首地址:" << &str1[0][1] << endl;cout << "str1[1][0]第二行行首的内存首地址:" << &str1[1][0] << endl;
-----------------------------------------------------------------------------------------
-2 -1 0
1 2 3
str1[][]二维数组占用的空间:24
str1[][]第一行占用的空间:12
str1[0][0]元素占用的空间:4str1[][]二维数组的行数:2
str1[][]二维数组的列数:3
str1[][]二维数组中所有元素个数:6str1[][]二维数组的内存首地址:00CFF844
str1[0][0]第一行行首的内存首地址:00CFF844
str1[0][1]元素的内存首地址:00CFF848
str1[1][0]第二行行首的内存首地址:00CFF850
请按任意键继续. . .

(2.3)二维数组应用案例

十、函数

(1)函数的定义

作用:将一段经常使用的代码封装起来,减少重复代码。

组成

1.返回值类型:一个函数可以返回一个值。

2.函数名:函数的名称。

3.参数列:使用函数时,传入的数据。

4.函数体语句:花括号内的代码,函数内需要执行的语句,用户代码。

5.return表达式:和返回值类型匹配。函数执行完后,返回相应数据。

语法

返回值类型  函数名 (参数列表)
{函数体语句return表达式
}int add (int num1, int num2)
{int sum = num1 + num2;return sum;
}int main(){/* 用户代码段 */// ...// ...system("pause");return 0;
}

(2)函数的调用,形参,实参

#include <iostream>
using namespace std;// 函数定义
int add(int num1, int num2) // int num1, int num2为形式参数,简称形参
{int sum = num1 + num2;return sum;
}int main() {// a,b称为 实际参数,简称实参int a = 11, b = 23;// 调用add函数int sum = add(a, b);cout << "a + b = " << sum << endl;system("pause");return 0;
}
------------------------------------------------------------------------
a + b = 34
请按任意键继续. . .

(3)值传递

要点:实参传递给形参后,形参的改变不会影响到实测。

#include <iostream>
using namespace std;// 函数定义
int test1(int num1, int num2)
{cout << "输入的 num1 = " << num1 << endl;cout << "输入的 num2 = " << num2 << endl;cout << endl;num1 += 10;num2 += 20;cout << "输出的 num1 = " << num1 << endl;cout << "输出的 num2 = " << num2 << endl;cout << endl;return 0;
}int main() {// a,b称为 实际参数,简称实参int a = 11, b = 23;cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;// 调用add函数test1(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;system("pause");return 0;
}
----------------------------------------------------------------------
a = 11
b = 23输入的 num1 = 11
输入的 num2 = 23输出的 num1 = 21
输出的 num2 = 43a = 11
b = 23请按任意键继续. . .

(4)函数的常见样式

常见的函数样式有4种:

1.无参无返

2.有参无返

3.无参有返

4.有参有返

(5)函数的声明

作用:告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

注意:函数的声明可以多次,但是函数的定义只能有一次。

#include <iostream>
using namespace std;// 函数的声明
int test1(int num1, int num2);int main() {// a,b称为 实际参数,简称实参int a = 11, b = 23;cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;// 调用add函数int max = test1(a, b);cout << "较大值 = " << max << endl;system("pause");return 0;
}// 函数定义
int test1(int num1, int num2)
{return num1 > num2 ? num1 : num2;
}
------------------------------------------------------------------
a = 11
b = 23较大值 = 23
请按任意键继续. . .

(6)函数的分文件编写

函数太多,不能写同一个文件中。而且功能混淆,不便于梳理、阅读、移植。

作用:让代码结构更加清晰。

函数的分文件编写一般有4个步骤:

1.创建后缀名为.h的头文件

2.创建后缀名为.cpp的源文件

3.在头文件中写函数的声明

4.在源文件中写函数的定义

将(5)的代码分文件编写:

demo.cpp

#include <iostream>
using namespace std;
#include "swap.h"int main() {// a,b称为 实际参数,简称实参int a = 11, b = 23;cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;// 调用add函数int max = swap(a, b);cout << "较大值 = " << max << endl;system("pause");return 0;
}

swap.cpp

#include "swap.h"// 函数定义
int swap(int num1, int num2)
{return num1 > num2 ? num1 : num2;
}

swap.h

#include <iostream>
using namespace std; // 函数的声明
int swap(int num1, int num2);

十一、指针

(1)指针的定义和使用

指针的作用:可以通过指针间接访问内存。

(1)指针变量的定义和使用:

指针变量定义语法:

数据类型  *  变量名;
#include <iostream>
using namespace std;int main() {int a = 13;int* p;// 指针指向数据a的地址p = &a;cout << "a的内存地址为:" << &a << endl;cout << "指针p为:" << p << endl;cout << endl;// 解引用*p = 100;cout << "a = " << a << endl;cout << "*p = " << *p << endl;system("pause");return 0;
}
------------------------------------------------------------
a的内存地址为:007FF988
指针p为:007FF988a = 100
*p = 100
请按任意键继续. . .

(2)指针所占用的空间

指针也是一种数据类型,这种数据类型占用多少内存字节呢?

#include <iostream>
using namespace std;int main() {int a = 13;int* p;// 指针指向数据a的地址p = &a;cout << "sizeof(int * ) = " << sizeof(int*) << endl;cout << "sizeof(float * ) = " << sizeof(float*) << endl;cout << "sizeof(double * ) = " << sizeof(double*) << endl;cout << "sizeof(char * ) = " << sizeof(char*) << endl;system("pause");return 0;
}Debug x86:------------------------------------------------------------------------
sizeof(int * ) = 4
sizeof(float * ) = 4
sizeof(double * ) = 4
sizeof(char * ) = 4
请按任意键继续. . .Debug x64:------------------------------------------------------------------------
sizeof(int * ) = 8
sizeof(float * ) = 8
sizeof(double * ) = 8
sizeof(char * ) = 8
请按任意键继续. . .

指针所占用的内存空间大小,只跟操作系统有关。32位系统为4字节,64位系统为8字节。

指针前面的数据类型,只是表示这段指针对应的值的数据类型,并不是指针的类型。

修改程序运行在32位、64位操作系统环境,在这里勾选 x86、x64。

(3)空指针

空指针:指针变量指向内存中编号为0的空间。

用途:初始化指针变量。

注意:空指针指向的内存是不可以访问的。

#include <iostream>
using namespace std;int main() {//空指针int* p = NULL;//*p = 100;cout << "指针p指向的内存地址: " << p << endl;cout << "指针p指向的值为: " << *p << endl;system("pause");return 0;
}
-------------------------------------------------------
指针p指向的内存地址: 00000000D:\VS_C++_PRJ\demo01\Debug\demo01.exe (进程 11668)已退出,代码为 -1073741819。
按任意键关闭此窗口. . .

(4)野指针

野指针:指针变量指向非法的内存空间。

注意:在程序中,尽量避免出现野指针。

#include <iostream>
using namespace std;int main() {//野指针int * p = (int *)0x21003000;//*p = 100;cout << "指针p指向的内存地址: " << p << endl;cout << "指针p指向的值为: " << *p << endl;system("pause");return 0;
}
---------------------------------------------------------------------------
指针p指向的内存地址: 21003000D:\VS_C++_PRJ\demo01\Debug\demo01.exe (进程 7944)已退出,代码为 -1073741819。
按任意键关闭此窗口. . .

(5)const修饰指针

const修饰指针有三种情况:
1.const修饰指针  ----  常量指针

2.const修饰指针  ----  指针常量

3.const既修饰指针,也修饰常量

const修饰指针  ----  常量指针:

int a = 10, b = 10;// 常量指针
// 特点:指针的指向可以修改,但是指针指向的值不可修改
const int * p = &a;*p = 20;    // 错误,指针指向的值不可以修改
p = &b;     // 正确,指针的指向可以修改

const修饰指针  ----  指针常量:

int a = 10, b = 10;// 指针常量
// 特点:指针的指向不可以修改,指针指向的值可以修改
int * const p = &a;*p = 20;    // 正确,指针指向的值可以修改
p = &b;     // 错误,指针的指向不可以修改

const既修饰指针,也修饰常量:

int a = 10, b = 10;// 指针常量
// 特点:指针的指向、指针指向的值,都不可以修改
const int * const p = &a;*p = 20;    // 错误,指针指向的值不可以修改
p = &b;     // 错误,指针的指向不可以修改

(6)指针和数组

作用:利用指针访问数组中的元素

int main() {int str1[10] = {11, 56, 82, 42, 85, 45, 89, 23, 41, 57};int* p = str1;cout << *p << endl;cout << *p + 1 << endl;cout << *(p + 1) << endl;p++;cout << *p << endl;system("pause");return 0;
}
-------------------------------------------------------------------
11
12
56
56
请按任意键继续. . .

(7)指针和函数(地址传递)

作用:利用指针做函数参数,可以修改实参的值。

与10.3值传递,对比着看。

要点:如果不想修改实参,就用值传递。如果想修改实参,就用地址传递。

int swap(int * num1, int * num2)
{int xtemp = *num1;*num1 = *num2;*num2 = xtemp;return 0;
}int main() {int a = 22;int b = 55;cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;swap(&a, &b);cout << "a = " << a << endl;cout << "b = " << b << endl;cout << endl;system("pause");return 0;
}
---------------------------------------------------------
a = 22
b = 55a = 55
b = 22请按任意键继续. . .

(8)指针、数组、函数,配合使用案例

十二、结构体

(1)结构体定义和使用

基本概念:结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。

结构体定义和使用:

语法:

struct  结构体名  { 结构体成员列表 };

通过结构体创建变量的方式有三种:

struct  结构体名  变量名;
struct  结构体名  变量名 = { 成员1值, 成员2值... };
定义结构体时顺便创建变量;

代码:

/* ------------------ 1.struct  结构体名  变量名; 之后进行赋值操作 ------------------ */
struct Student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};int main() {//struct Student xiaoMing;Student xiaoMing;   // struct关键字可以省略xiaoMing.name = "小明";xiaoMing.age = 18;xiaoMing.score = 96;xiaoMing = { "小明", 18, 96 };cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;system("pause");return 0;
}/* -------------- 2.struct  结构体名  变量名 = { 成员1值, 成员2值... }; -------------- */
struct Student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};int main() {Student xiaoMing = {"小明", 18, 96};cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;system("pause");return 0;
}/* -------------------- 3.定义结构体时顺便创建变量; -------------------- */
struct Student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};int main() {xiaoMing.name = "小明";xiaoMing.age = 18;xiaoMing.score = 96;xiaoMing = { "小明", 18, 96 };cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;system("pause");return 0;
}
-----------------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
请按任意键继续. . .

使用 typedef 定义 struct 结构体方法:https://blog.csdn.net/Mark_md/article/details/107656790

(2)结构体数组

作用:将自定义的结构体放入到数组中,方便维护。

语法:

struct  结构体名  数组名[ 元素个数 ] = { {}, {}, ... {} };
struct Student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};int main() {struct Student stuArray[3] ={{ "小明", 18, 96 },{ "小红", 20, 100 },{ "小亮", 21, 98 }};for (int i = 0; i < 3; i++){cout << "姓名:" << stuArray[i].name << "  年龄:" << stuArray[i].age << "  分数:" << stuArray[i].score << endl;}system("pause");return 0;
}
----------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:小红  年龄:20  分数:100
姓名:小亮  年龄:21  分数:98
请按任意键继续. . .

(3)结构体指针

作用:通过指针访问结构体中的成员。

利用操作符 -> 可以通过结构体指针访问结构体属性。

示例:

struct Student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};int main() {struct Student xiaoMing = { "小明", 18, 96 };Student* p = &xiaoMing;cout << "姓名:" << p->name<< "  年龄:" << p->age<< "  分数:" << p->score << endl;system("pause");return 0;
}
-----------------------------------------------------------------
姓名:小明  年龄:18  分数:96
请按任意键继续. . .

(4)结构体嵌套

结构体嵌套结构体:

作用:结构体中的成员可以是另一个结构体。

例如:每个老师辅导一个学员,老师的结构体中,记录学生的结构体。

示例:

struct student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};struct teacher
{int id;            // 职工编号string name;     // 教师姓名int age;     // 教师年龄struct student stu;  // 子结构体 学生
};int main() {teacher wang;wang.id = 112374;wang.name = "王芳";wang.age = 26;wang.stu.name = "小明";wang.stu.age = 18;wang.stu.score = 96;cout << "教师姓名:" << wang.name<< "  教师年龄:" << wang.age<< "  教师ID号:" << wang.id << endl;cout << "学生姓名:" << wang.stu.name<< "  学生年龄:" << wang.stu.age<< "  学生分数:" << wang.stu.score << endl;system("pause");return 0;
}
-------------------------------------------------------------------------
教师姓名:王芳  教师年龄:26  教师ID号:112374
学生姓名:小明  学生年龄:18  学生分数:96
请按任意键继续. . .

(5)结构体做函数参数

作用:将结构体作为参数向函数中传递

传递方式分两种:值传递,地址传递。

值传递示例:

struct student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};void printStudent(student stu)
{cout << "姓名:" << stu.name<< "  年龄:" << stu.age<< "  分数:" << stu.score << endl;stu.name = "无";stu.age = 0;stu.score = 0;
}int main() {student xiaoMing = { "小明", 18, 96 };printStudent(xiaoMing);cout << "姓名:" << xiaoMing.name<< "  年龄:" << xiaoMing.age<< "  分数:" << xiaoMing.score << endl;system("pause");return 0;
}
---------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:小明  年龄:18  分数:96
请按任意键继续. . .

地址传递示例:

struct student
{// 成员列表string name;    // 姓名int age;   // 年龄int score; // 分数
};void printStudent(student * stu)
{cout << "姓名:" << stu->name<< "  年龄:" << stu->age<< "  分数:" << stu->score << endl;stu->name = "无";stu->age = 0;stu->score = 0;
}int main() {student xiaoMing = { "小明", 18, 96 };printStudent(&xiaoMing);cout << "姓名:" << xiaoMing.name<< "  年龄:" << xiaoMing.age<< "  分数:" << xiaoMing.score << endl;system("pause");return 0;
}
--------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:无  年龄:0  分数:0
请按任意键继续. . .

如果不想实参结构体内容,用值传递,反之用地址传递。

地址传递还可以使用数组,可实现同样功能,书写与阅读比指针更加直观。

(6)结构体中const使用场景

作用:用const来防止误操作

值传递会copy,会占内存空间,复制也会多花时间。所以如果可以用地址传递,可以提高执行效率。

而地址传递可能会对原始对象进行误修改,这时候就可以加 const。如果出现修改,编译器会报错

示例:

void printStudent(const student * stu)
{cout << "姓名:" << stu->name<< "  年龄:" << stu->age<< "  分数:" << stu->score << endl;stu->name = "无";    // 编译器会报错stu->age = 0;stu->score = 0;
}

c/c++教程 - 总集1. c基础语法相关推荐

  1. python菜鸟基础教程-python基础菜鸟教程,Python的基础语法

    原标题:python基础菜鸟教程,Python的基础语法 什么是Python?Python是一门简单直观的编程语言,并且目前是开源的,可以方便任何人使用. Python的开发哲学:用一种方法,最好是只 ...

  2. python基础教程菜鸟教程-python基础菜鸟教程,Python的基础语法

    原标题:python基础菜鸟教程,Python的基础语法 什么是Python?Python是一门简单直观的编程语言,并且目前是开源的,可以方便任何人使用. Python的开发哲学:用一种方法,最好是只 ...

  3. java系统教程_Java 教程(开发环境配置+基础语法)

    Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. window系统安装java 下载JDK 首先我们需要下载java开发工具包JDK,下载地址:http://www.ora ...

  4. 0基础java语法_Java零基础教程(二)基础语法

    Java 基础语法 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如 ...

  5. python 语言教程(2)基础语法之标识符

    1. 标识符 可以包括英文.数字以及下划线(_),但不能以数字开头.(区分大小写) 下划线开头的标识符 以单下划线开头代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx i ...

  6. python 语言教程(2)基础语法

    1. 注释 单行注释采用 # # 第一个注释 print ("Hello, Python!") # 第二个注释 name = "Madisetti" # 这是一 ...

  7. 【JavaScript系列】JS基础语法_从变量到数组一网打尽_有教程有实战

    [JavaScript系列]基础语法_从变量到数组一网打尽_有教程有实战 JavaScript基础语法目录 基础语法 延迟和异步脚本 变量 数据类型 数据类型简介 简单数据类型与复杂数据类型 栈和堆 ...

  8. Xamarin XAML语言教程基础语法篇大学霸

    Xamarin XAML语言教程基础语法篇大学霸 前  言 Xamarin是一个跨平台开发框架.它可以用来开发iOS.Android.Windows Phone和Mac的应用程序.使用Xamarin框 ...

  9. python设计一个函数定义计算并返回n价调和函数_音乐编程语言musicpy教程(第三期) musicpy的基础语法(二)...

    这个是我在github上给我的项目musicpy写的wiki,分为数据结构,基础语法,实际应用三大部分来为大家讲解这门音乐编程语言,主要是想给大家写一个musicpy的详细的教程与介绍,目前wiki只 ...

最新文章

  1. AI黑科技:呵护地球,我们是认真的
  2. Java 理论与实践: 流行的原子——新原子类是 java.util.concurrent 的隐藏精华(转载)...
  3. 关于日期比较compareTo
  4. KVM半虚拟化驱动--virtio概述和基本原理(四)
  5. 大厂php怎么做前端,大厂前端经典面试问题精选(附答案)
  6. 【C++】【TinyXml】xml文件的读写功能使用——写xml文件
  7. Servlet 3.0 新特性详解
  8. 《ArcGis地图数据资料》(DataMap)ArcGis 9.0
  9. 远程桌面登录 Windows Server 2003时提示无权限
  10. ActiveMQ 无法启动 提示端口被占用 解决方案
  11. 从“运维”处谈OFO失败
  12. OpenCV(VS2019)——无法打开“opencv2/opencv.hpp”文件
  13. 【Unity Shaders】ShadowGun系列之一——飞机坠毁的浓烟效果
  14. Arduino学习笔记——数字输入
  15. go语言下载gin失败解决方案
  16. 小强升职记(GTD)脑图
  17. ”网上花店” 专题页制作
  18. 2020学期学习计划
  19. OSChina 周六乱弹 ——开发个专门用于拉shi的APP
  20. v-charts legend设置排列对齐的方法

热门文章

  1. 返回一个整数数组中最大子数组的和。
  2. docker版mysql的使用和配置(2)——docker版mysql的dockerfile
  3. sklearn-preprocessing预处理数据的方法
  4. 正则表达式之子表达式 ‘()’ 中表达式 '[]' 大表达式 '{}'
  5. 组态王和modbus协议
  6. poj 3384 Feng Shui (Half Plane Intersection)
  7. 田永强:优秀的JavaScript模块是怎样炼成的
  8. 【网络安全工程师面试题】数据库存在的漏洞及渗透方法
  9. Linux运维问题解决(1)——Linux 定时任务 crontab 配置及示例
  10. Linux系统管理(9)——系统状态监控命令top使用详解