c/c++教程 - 总集1. c基础语法
发布日期:2021-05-07 13:31:50 浏览次数:26 分类:精选文章

本文共 23895 字,大约阅读时间需要 79 分钟。

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

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

开发环境搭建

推荐教程视频

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

 

一、代码的注释

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

// 单行注释/* ...   ...   多行注释   ...   ... */#include 
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 
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 编码对照表:

 

(4)转义字符

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

对照表:

 

(5)字符串类型

表示一串字符。

C风格字符串:

char str1[] = "123abc";

C++风格字符串:

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

 

(6)布尔类型

代表真或假的值。

bool的值只有两个:

true - 真,1

false - 假,0

 

(7)数据的输入

用于从键盘获取数据。

语法:cin >> 变量

 

(8)sizeof 统计内存大小

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

sizeof(数据类型/变量)
#include 
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 占用空间:2int 占用空间:4long 占用空间:4long long 占用空间:8float 占用空间:4double 占用空间:8char 占用空间:1bool 占用空间:1请按任意键继续. . .

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 ij j j j j j j j j j ij j j j j j j j j j ij j j j j j j j j j ij 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 ij j j j j ij j j j j ij j j j j ij 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;	}--------------------------------------------------------01234679i01234679i01234679i01234679i01234679i请按任意键继续. . .

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 2str1[]整个数组占用的空间:20str1[0]元素占用的空间:4str1[]数组中元素个数:5str1[]数组的内存首地址:00D8FA64str1[0]元素的内存首地址:00D8FA64str1[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 2str1[]数组中元素个数:5str1[]数组中第几个元素为最大值: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 22 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 01 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 01 2 3str1[][]二维数组占用的空间:24str1[][]第一行占用的空间:12str1[0][0]元素占用的空间:4str1[][]二维数组的行数:2str1[][]二维数组的列数:3str1[][]二维数组中所有元素个数:6str1[][]二维数组的内存首地址:00CFF844str1[0][0]第一行行首的内存首地址:00CFF844str1[0][1]元素的内存首地址:00CFF848str1[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 
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 
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 = 11b = 23输入的 num1 = 11输入的 num2 = 23输出的 num1 = 21输出的 num2 = 43a = 11b = 23请按任意键继续. . .

 

(4)函数的常见样式

常见的函数样式有4种:

1.无参无返

2.有参无返

3.无参有返

4.有参有返

 

(5)函数的声明

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

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

#include 
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 = 11b = 23较大值 = 23请按任意键继续. . .

 

(6)函数的分文件编写

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

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

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

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

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

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

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

 

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

demo.cpp

#include 
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 
using namespace std; // 函数的声明int swap(int num1, int num2);

 

十一、指针

(1)指针的定义和使用

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

 

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

指针变量定义语法:

数据类型  *  变量名;
#include 
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 
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 * ) = 4sizeof(float * ) = 4sizeof(double * ) = 4sizeof(char * ) = 4请按任意键继续. . .Debug x64:------------------------------------------------------------------------sizeof(int * ) = 8sizeof(float * ) = 8sizeof(double * ) = 8sizeof(char * ) = 8请按任意键继续. . .

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

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

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

 

(3)空指针

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

用途:初始化指针变量。

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

#include 
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 
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;}-------------------------------------------------------------------11125656请按任意键继续. . .

 

(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 = 22b = 55a = 55b = 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 结构体方法

 

(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;}

 

上一篇:CSDN设置插入代码的背景色为黑色 csdn更改背景色、主题
下一篇:模拟开关选型、多路复用器选型

发表评论

最新留言

关注你微信了!
[***.104.42.241]2025年03月27日 19时27分49秒