编程成长之路

我们都是站在父母的肩上去看他们不曾看到的风景!加油!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++基础

Posted on 2024-06-24 21:14  来颗维C  阅读(35)  评论(0编辑  收藏  举报

一、C++第一个项目

入门技巧

  • 1.使用解决方案资源管理器窗口添加/管理文件
  • 2.使用团队资源管理器窗口连接到源代码管理
  • 3.使用输出窗口查看生成输出和其他消息
  • 4.使用错误列表窗口查看错误
  • 5.转到"项目"-->"添加新项"以创建新的代码文件 或者转到"项目"-->"添加现有项"添加到项目中
  • 6.将来若要再次打开此项目,选择.sIn文件

代码:

#include <iostream>  //包含的头文件

using namespace std;  //缺省指定的命名空间

int main()   //程序入口 程序执行的入口 每个程序有且仅有一个main函数
{
 //<< 输出运算符
 //cout 向控制台输出内容的指令
 // ; C++语句结束符
	cout << "HelloWorld!" << endl;      

	return 0;
}

二、C++输出数据

数据是信息的载体,写程序的目的就是为了处理数据

1.数据的分类

数据有数字、字符和字符串三种类型

数字:直接书写,如100、89、23;

字符:用半角的单引号包含的一个符号,如:'A'、'z'、'0'、‘9’ 、‘~’、‘+’等;

字符串:用半角的双引号包含的多个符号,如:"Hello World";

2.输出数据

std::cout 可以输出各种类型的数据;

<<操作符可以拼接多个数据项;

std::eddl 也可以用于换行;

using namespace std;制定缺省的命名空间

3.示例代码

#include <iostream>
using namespace std;

int main()
{
	//用于多个数据项的输出: 姓名、年龄、性别、学号、专业
	cout << "姓名" << "C++初学者" << endl << "年龄:" << 25 << endl << "性别:" << "男" << endl << "学号:" << 20990164 << endl << "专业:" << "计算机科学与技术" << endl;
	return 0;
}

解决VS编译中文报错 error C2001:常量中有换行符

产生原因:文件中有中文字符,但是文件是utf-8格式的,使用msvc编译器编译时就会产生上述错误

解决办法:

方式1(不推荐试了没用):

​ 通过在项目里设置编译选项,/utf-8

​ 项目->右键属性->C/C++ -> 命令行,在下方输入框添加 /utf-8,就会在编译时采用utf-8编码来编译

image-20240531212810579

方式3:(亲测可用已解决,但是这种方法会使原有项目在使用vs打开时出现中文乱码)

打开控制面板-->找到时钟和区域

image-20240531214713642

找到区域

image-20240531214746231

点击管理-->更改系统区域设置

image-20240531214829574

勾选上Beta-->重启电脑

image-20240531214932706

三、指针的基本概念

1、变量的地址

变量是内存变量的简称,在C++中,每定义一个变量,系统就会给变量分配一块内存,内存是有地址的。

c++中使用运算符&获取变量在内存中的起始地址。

2指针变量

指针变量简称指针,它是一种特殊的变量,专门用于存放变量在内存中的起始地址。

语法:数据类型*变量名;

数据类型必须是合法的C++数据类型

#include <iostream>

using namespace std;

int main()
{
	int a;
	char b;
	bool c;
	string d;

	//int* pa = &a;  //让指针pa指向变量a
	//char* pb = &b; //r让指针pb指向变量b
	//bool* pc = &c;
	//string* pd = &d;

	int* pa;  //定义指针pa
	char* pb;
	bool* pc;
	string* pd;

	a = 1;

	/*cout << "变量a的地址是:" << (long long)&a << endl;
	cout << "变量b的地址是:" << (long long)&b << endl;
	cout << "变量c的地址是:" << (long long)&c << endl;
	cout << "变量d的地址是:" << (long long)&d << endl;
	cout << endl;

	cout << "指针变量a的地址是:" << (long long)pa << endl;
	cout << "指针变量b的地址是:" << (long long)pb << endl;
	cout << "指针变量c的地址是:" << (long long)pc << endl;
	cout << "指针变量d的地址是:" << (long long)pd << endl;
	cout << endl;

	cout << sizeof(pa) << endl;
	cout << sizeof(pb) << endl;
	cout << sizeof(pc) << endl;
	cout << sizeof(pd) << endl;

	return 0;*/
}

3.使用指针

声明指针变量后,在没有赋值之前, 里面是乱七八糟的值, 这时候不能使用指针。
指针存放变量的地址,因此,指针名表示的是地址(就像变量名可以表示变量的值一样)
*运算符被称为间接值或解除引用(解引用) 运算符,将它用于指针,可以得到该地址的内存中存储
的值, *也是乘法符号, C++根据上下文来确定所指的是乘法还是解引用

#include<iostream>
using namespace std;
int main()
{
//定义一个变量
	int a;
	//初始化变量
	a = 3;

	//定义一个指针
	int* p = &a;

	//输出a的值
	cout << "a=" << a << endl;
	cout << "*p=" << *p << endl;

	//对指针p解引用并且赋值
	*p = 8;
	cout << "a=" << a << endl;
	cout << "*p=" << *p << endl;

}

4.指针用于函数的参数

如果把函数的形参声明为指针,调用的时候把参数的地址传进去,形参中存放的是实参的地址,在函数中通过解引用的方法直接操作内存中的数据,可以修改实参的值,这种方法称为地址传递或者传地址

传地址的意义:可以在函数中修改实参的值.减少内存拷贝,提升性能

#include <iostream>

using namespace std;

//函数声明
void func(int num, string str);

int main()
{
	int bh = 3;
	string message = "峡谷掉分王";

	//函数调用
	func(bh, message);
	/*下边代码模拟函数调用的过程,等同于func(bh,message);
	 *{
		int num = bh;
		string str = message;
		cout << "亲爱的" << num << "号:" << str << endl;
	}*/
}

//函数定义
void func(int num, string str)
{
	cout << "王者荣耀" << num << "号:" << str << endl;
}

值传递:在代码中修改形参的不会改变实参的值

四、用const修饰指针

1、常量指针

语法:const 数据类型 *变量名

不能通过解引用的方法修改内存地址中的值(用原始的变量名是可以修改的)

#include <iostream>

using namespace std;

int main()
{
	//定义普通变量 语法:数据类型 变量名;
	int a = 3;
	int b = 8;

	//定义常量指针 语法:const 数据类型 *变量名
	const int* p = &a;  //使用取地址符&将普通变量a的值复制给常量指针p
	cout << "a=" << a << endl;  //输出结果 3
	cout << "*p=" << *p << endl;  //输出结果 3

}

输出结果

image-20240608104139427

通过解引用修改常量指针的值

#include <iostream>

using namespace std;

int main()
{
	//定义普通变量 语法:数据类型 变量名;
	int a = 3;
	int b = 8;

	//定义常量指针 语法:const 数据类型 *变量名
	const int* p = &a;  //使用取地址符&将普通变量a的值复制给常量指针p

 //修改常量指针的值
	*p = 13; //这种方式是通过解引用的方法修改内存地址中的值 报错

	cout << "a=" << a << endl;  //输出结果 3
	cout << "*p=" << *p << endl;  //输出结果 3


}

运行报错

image-20240608104254162

用原始变量名可以修改

#include <iostream>

using namespace std;

int main()
{
	//定义普通变量 语法:数据类型 变量名;
	int a = 3;
	int b = 8;

	//定义常量指针 语法:const 数据类型 *变量名
	const int* p = &a;  //使用取地址符&将普通变量a的值复制给常量指针p

	//修改常量指针的值
	//*p = 13; //这种方式是通过解引用的方法修改内存地址中的值

	//用原始变量名修改内存地址中的值(可以修改)
	a = 13;

	cout << "a=" << a << endl;  //输出结果 3
	cout << "*p=" << *p << endl;  //输出结果 3
}

运行结果(可以修改成功)

image-20240608104925139

指向变量(对象可以改变)(之前是指向变量a的 后来可以改为指向变量b)

#include <iostream>

using namespace std;

int main()
{
	//定义普通变量 语法:数据类型 变量名;
	int a = 3;
	int b = 8;

	//定义常量指针 语法:const 数据类型 *变量名
	const int* p = &a;  //使用取地址符&将普通变量a的值复制给常量指针p

	//修改常量指针的值
	//*p = 13; //这种方式是通过解引用的方法修改内存地址中的值

	//用原始变量名修改内存地址中的值(可以修改)
	a = 13;

	cout << "a=" << a << endl;  //输出结果 3
	cout << "*p=" << *p << endl;  //输出结果 3

	//原本是指向a修改后指向b
	p = &b;
	cout << "b=" << endl;
	cout << "p=" << *p << endl;
}

image-20240608105458107

常量指针的应用场景

一般用于修饰函数的参数,表示不希望在函数里修改内存地址的值

2、指针常量

语法: 数据类型 *const 变量名

指向的变(对象)不可以改变,在定义的同时必须初始化;可以通过解引用的方法修改内存地址中的值

在定义的同时必须初始化(没有初始值会报错)

image-20240608125120062

在定义的时候赋初始值

image-20240608125718923

指向变量不可以改变(之前是指向变量a 不可以再指向变量b)

#include <iostream>
using namespace std;


int main()
{
  int a = 3;
	int b = 8;
	int* const p = &a;
	//使用解引用的方法去修改内存地址中的值
	*p = 13;
	cout << "a=" << a << endl;
	cout << "*p=" << *p << endl;

	//之前指向a,现在将指针常量指向b  不可以改变
	p = &b;//报错
}

image-20240608130101026

3、常指针常量

语法: const 数据类型 *const 变量名;

指向变量(对象)不可以改变 不能通过解引用的方法修改内存地址中的值

4、常量指针、指针常量、常指针常量

常量指针:原先常量指针的指向原始变量a,可以通过修改 原始变量a的值来修改常量指针的值,但是不能通过修修改指针变量的值来修改原始变量的值;并且常量指针可以有原先指向变量a改为转向变量b;

//定义普通变量 语法:数据类型 变量名;
	int a = 3;
	int b = 8;

	//定义常量指针 语法:const 数据类型 *变量名
	const int* p = &a;  //使用取地址符&将普通变量a的值复制给常量指针p

	//修改常量指针的值
	//*p = 13; //这种方式是通过解引用的方法修改内存地址中的值 报错

	//用原始变量名修改内存地址中的值(可以修改)
	a = 13;

	cout << "a=" << a << endl;  //输出结果 3
	cout << "*p=" << *p << endl;  //输出结果 3

	//原本是指向a 可以指向b
	p = &b;
	cout << "b=" << b << endl;
	cout << "p=" << *p << endl;

指针常量:原先指针常量指向原始变量a,可以通过修改常量指针的值来修改原始变量a的值,并且指针常量不可以由原先指向变量a改为转向变量b;

常指针常量:指针指向不可以改,指针指向的值也不可以该(原先指针常量指向原始变量a,不可以通过修改常量指针的值来修改原始变量a的值,不可以由原先指向变量a改为转向变量b;)

5、void关键字

在C++中,void 表示无类型,主要三个用途:

函数的返回值用void,表示函数没有返回值。

void func(int ,int b)
{
 //函数体代码
 return;
}

函数的参数填void,表示函数不需要参数或者让参数列表空着

int fun(void)
{
//函数体代码
}

函数的参数用void*,表示接受任意数据类型的指针

注意:

不能用void声明变量,他不能代表一个真实的变量

不能对void*指针解引用(需要转换成其他类型的指针)

把其它类型的指针赋值给void*指针不需要转换

解引用的时候需要知道书局占用内存空间的大小

没有使用void*的时候会出现"烫烫烫烫烫"

image-20240608160335548

使用void*解决上边问题

image-20240608160434455

另一种方法: 写一个函数来实现:函数有两个形参:一个变量名,另外一个存地址,不需要返回值

#include <iostream>

using namespace std;

//声明函数
void func(string varname, int* p);  //如果将int*型指针改为void*指针不需要在调用函数是进行强制转换

int main()
{
	//显示变量十六进制地址
	int a;
	char b;
	cout << "a的地址是:" << &a << endl;
	cout << "b的地址是:" << &b << endl;

	//函数调用
	func("a", &a);
	//func("b", &b);//报错 不能将字符指针转换成整形指针
	func("b", (int*)&b);  //需要将字符指针转换成整形指针

	/*cout << "a的地址是:" << (void*)&a << endl;
	cout << "b的地址是:" << (void*)&b << endl;*/
}

//函数定义
void func(string varname, int* p)
{
	cout << varname << "地址是:" << p << endl;
}

image-20240608161841727

6、C++内存模型

内存空间:从地址从低到高代码段(存放程序中的二进制代码)、数据段(存放全局变量、静态变量)、(由程序员管理,需要手动 new malloc delete free 进行分配和回收,空间较大,可能会出现内存泄漏和空闲碎片的情况、堆是向上增长)、(由编译器管理分配和回收,存放局部变量和函数参数、栈是向下增长)

栈和堆的区别:

1、管理方式不同:栈是需要系统管理分配和回收;堆则需要程序员手动new malloc delete free 分配和回收

2、空间大小不同:堆内存空间大小受限于物理内存空间(内存越大,分配的空间就越多);而栈的就特别小,一般只有8M(修改系统参数可以修改栈的大小)

3、分配方式不同:堆是动态分配;栈有动态分配和静态分配

4、分配效率不同:栈是系统提供的数据结构,计算机在底层提供了对栈的支持,进栈和出栈有专门指令,效率比较;堆是由C++函数库提供

7、动态分配内存 new 和 delete

//动态分配内存的步骤
//1.声明一个指针
// 2.用new运算符想系统申请一块内存,让指针指向这块内存
// 3.通过指针解引用方法,像使用变量一样使用这块内存
// 4.如果这块内存不用了,用delete运算符释放这块内存
// 申请内存的语法:new 数据类型(初始值) // c++11
// 释放内存语法:delete 地址;

#include <iostream>  //包含头文件
using namespace std;  //指定缺省的命名空间

int main()  //程序的入口
{
	//动态分配内存的步骤
	//1.声明一个指针
	int* p;
	// 2.用new运算符想系统申请一块内存,让指针指向这块内存
	p = new int(5);
	// 3.通过指针解引用方法,像使用变量一样使用这块内存
	cout << "*p=" << *p << endl;
	*p = 8;  //解引用
	cout << "*p=" << *p << endl;
	// 4.如果这块内存不用了,用delete运算符释放这块内存
	delete p;

	// 申请内存的语法:new 数据类型(初始值)  //	c++11
	// 释放内存语法:delete 地址;

	return 0;
}

image-20240609104357926

注意:

1、如果动态分配内存不用了,必须要用delete释放,否则有可能用尽系统的内存;

2、动态分配的内存生命周期与程序相同,程序退出时,如果没有释放,系统将自动回收

8、二级指针

指针指针变量的简称,也是变量,是变量就有地址

指针用于存放普通变量地址

二级指针用于存放指针变量地址

声明二级指针的语法:数据类型** 指针名;

使用指针有两个目的:(1)传递地址;(2)存放动态分配的内存地址。

在函数中,如果传递普通变量的地址,形参用指针;传递指针的地址的地址,形参用二级指针;

#include <iostream>  //包含头文件
using namespace std; //指定缺省的命名空间

int main()
{
	//先声明一个普通变量i;
	int i;
	//变量初始化赋值为8
	i = 8;
	//显示这个变量的值和地址
	cout << "i的值=" << i << endl;
	cout << "i的地址是:" << &i << endl;
	cout << endl;

	//在声明一个指针pi,让它指向变量i
	int* pi = &i;
	cout << "pi的值=" << pi << endl;
	cout << "pi的地址是:" << &pi << endl;
	//解引用的结果
	cout << "*pi的值=" << *pi << endl;
	cout << endl;

	//声明二级指针
	int** ppi = &pi;
	cout << "ppi的值=" << ppi << endl;
	cout << "ppi的地址是:" << &ppi << endl;
	cout << "*ppi的值=" << *ppi << endl;
	cout << endl;
	cout << "**pi的值=" << **ppi << endl;
}

image-20240609123851959

9.空指针

在C和C++中,用0或者NULL都可以表示空指针

声明指针后,在赋值之前,让它指向空,表示没有指向任何地址.

1、使用空指针的后果

如果对空指针解引用,程序会崩溃。

image-20240609155325348

如果对空指针使用delete运算符,系统将忽略该操作,不会出现异常。所以内存释放后,也应该把指针指向空。

image-20240609155510863

image-20240609161642658

使用空指针方式定义函数就会导致程序蹦崩溃

#include <iostream>  //包含头文件
using namespace std;  //指定缺省的命名空间

//函数声明
void func(int* no, string* str);

int main()
{
	////声明编号
	//int bh = 3;
	////声明信息
	//string message = "我是C++程序员";
	////函数调用
	//func(&bh, &message);

	/**使用指针方式**/

	//使用空指针声明编号
	int* bh = 0; /*new int(3);*/
	//使用空指针声明信息
	string* message = 0; /*new string("杭州智诺科技");*/

	//函数调用
	func(bh, message);

	//释放内存
	delete bh;
	delete message;
}

//函数定义
void func(int* no, string* str)
{
	cout << "你好" << *str << "我是" << *no << "号" << "韦广豪" << endl;  //程序崩溃的原因:因为使用空指针,解引用就成了非法操作
}

image-20240609163455107

问题解决方法:在定义函数中增加判断代码,如果形参是空指针,就返回不要继续执行下面的流程

#include <iostream>  //包含头文件
using namespace std;  //指定缺省的命名空间

//函数声明
void func(int* no, string* str);

int main()
{
	////声明编号
	//int bh = 3;
	////声明信息
	//string message = "我是C++程序员";
	////函数调用
	//func(&bh, &message);

	/**使用指针方式**/

	//使用空指针声明编号
	int* bh = 0; /*new int(3);*/
	//使用空指针声明信息
	string* message = 0; /*new string("杭州智诺科技");*/

	//函数调用
	func(bh, message);

	//释放内存
	delete bh;
	delete message;
}

//函数定义
void func(int* no, string* str)
{
 //判断形参是否为空指针的代码
	if ((no==0) || (str==0))
	{
		return;
	}
 //目的:保证代码的健壮性

	cout << "你好" << *str << "我是" << *no << "号" << "韦广豪" << endl;
}

image-20240609164124630

解决程序崩溃问题,但是没有显示任何内容;

C++11的 nullptr

C++11建议使用nullptr表示空指针,也就是(void*)0

10.野指针

野指针:就是指针指向的不是一个有效的地址;

image-20240609170053208

报错原因:不能将十六进制数转换为指针

解决办法:强制类型转换(但是会地址显示没问题,但是解引用失败 程序崩溃)

image-20240609170420376

在程序中,如果访问野指针,可能会造成程序崩溃

出现野指针的情况主要有三种:

1、指针在定义的时候,如果没有进行初始化,它的值是不确定的

image-20240609170717081

(也就是说指针在没有初始化之前编译器不让使用该指针)

2、如果用指针指向了动态分配的内存,内存被释放后,指针不会置空,但是指向地址已失效

#include <iostream>  //包含的头文件
using namespace std;  //指定缺省的命名空间

int main()
{
	//声明一个指针并分配一块内存空间
	int* p;
	p = new int(3);

	//显示指针值和对p解引用的结果
	cout << "p=" << p << endl;
	cout << "*p=" << *p << endl;

	delete p;

	cout << "p=" << p << endl;
	cout << "*p=" << *p << endl;
}

image-20240609171401994

(解释:释放内存,程序崩溃)

3、指针指向的变量已超越变量的作用域(变量的内存空间已被系统回收)

#include <iostream>  //包含的头文件
using namespace std;  //指定缺省的命名空间

//声明函数
int* func();

int main()
{
	//声明一个指针
	int* p;
	//函数调用
	func();

	//将函数func复制给指针p
	p = func();  //相当于 int*p=func();

	//显示指针值和对p解引用的结果
	cout << "p=" << p << endl;
	cout << "*p=" << *p << endl;
}

//函数的定义
int* func()
{
	//定义一个变量
	int a = 3;
	//显示结果
	cout << "a=" << a << endl;
	cout << "a的地址是:" << &a << endl;

	return &a;
}

image-20240609172342924

避免出现野指针的方法:

1、在定义的时候,如果没地方指,就初始化为nullptr。

2、动态分配的内存被释放后,将其置为nullptr。

3、函数不要返回局部变量的地址。

11、函数指针和回调函数

函数指针:

函数的二进制代码存放在内存区四区中的代码段,函数的地址它在内存中的开始地址。如果把函数的地址作为参数,就可以在函数中灵活调用其他函数。

使用函数指针的三个步骤:

1、声明函数指针;

声明普通指针时,必须提供指针的类型。同样声明函数指针时,也必须提供函数类型,函数类型是指返回值参数列表

#include<iostream>  //包含的头文件
using namespace std;  //指定缺省的命名空间

//声明函数指针
void (*pfunc)(int, string);

//普通函数声明
void func(int no, string str);

int main()
{
	int bh = 3;
	string message = "C++开发者";

	//普通函数的函数调用
	func(bh, message);

	//对函数指针赋值
	pfunc = func;  //语法 : 函数指针名=函数名;
	//使用函数指针名调用函数
	pfunc(bh, message);
}

//普通函数的定义
void func(int no, string str)
{
	cout << "你好" << no << "号:" << str << endl;
}

2、让函数指针指向函数的地址;


3、通过函数指针调用函数。

//对函数指针赋值
	pfunc = func;  //语法 : 函数指针名=函数名;
	//使用函数指针名调用函数
	pfunc(bh, message);

普通函数的调用方式:

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

//声明函数
void func(int no, string str);

int main()
{
	//声明编号
	int bh = 3;
	//声明信息
	string message = "我是C++开发者";

	//函数调用
	func(bh, message);
}

//函数定义
void func(int no, string str)
{
	cout << "你好" << no << "号" << str << endl;
}

回调函数:

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

void 个性化表白函数()
{
	//个性化表白的代码
}

void 表白神器(个性化表白函数指针p)
{
	个性化表白函数指针p();
}

int main()
{
	表白神器(个性化表白函数名);
}

代码填充

//函数的回调
#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间
//回调函数1
void func1()  //个性化表白函数
{
	cout << "我是C++开发" << endl;
}
//回调函数2
void func2()
{
	cout << "我是C开发者" << endl;
}
//调用者函数
void show(void(*pf)())
{
	//工作前的准备
	cout << "工作前准备已经完成" << endl;
	//用函数指针名调用个性化表白函数
	pf();
	//尾工作
	cout << "收尾工作已完成" << endl;
}

int main()
{
	//调用功能函数
	show(func1);
}

12、一维数组

数组是一组数据类型相同的变量,可以存放一组数据。

1、创建数组

声明数组的语法:数据类型 数组名[数组长度]

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

int main()
{
	//创建数组
	int bh[3];  //编号
	string name[3]; //姓名

	//可以通过数组下表访问数组元素,数组下标从0开始.
	//数组中的每个元素特征和使用方法与单个变量完全相同

	bh[0] = 3; //第0个
	bh[1] = 5; //第1个
	bh[2] = 8; //第2个

	cout << "bh[0]=" << bh[0] << endl;
	cout << "bh[1]=" << bh[1] << endl;
	cout << "bh[2]=" << bh[2] << endl;

	cout << endl;

	//可以使用变量来创建数组
	//创建变量i
	int i;
	//将i赋值为 表示第0个
	i = 0;
	//将数组下标用变量表示
	bh[i] = 3;

	//将i赋值为1  表示第1个
	i = 1;
	//将数组下标用变量表示
	bh[i] = 5;

	//将i赋值为2  表示第2个
	i = 2;
	bh[i] = 8;

	i = 0;
	cout << "bh[0]=" << bh[i] << endl;
	i = 1;
	cout << "bh[1]=" << bh[i] << endl;
	i = 2;
	cout << "bh[2]=" << bh[i] << endl;
}

注意:数组长度必须是整数,可以是常量,也可以是变量和表达式

处理数组的常用方法:使用循序:for循环和while循环都可以

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

int main()
{
	//创建数组
	int bh[3];  //编号
	string name[3]; //姓名

	//可以通过数组下表访问数组元素,数组下标从0开始.
	//数组中的每个元素特征和使用方法与单个变量完全相同

	for (int i = 0; i < 3; i++)  //i要小于数组长度
	{
		bh[i] = 30 + i;  //循环第0次,i的值是0,编号是30  循环第1次,i的值是1 编号是31 循环第二次,i的值是2 编号是32
	}
	int i;

	i = 0;
	cout << "bh[0]=" << bh[i] << endl;
	i = 1;
	cout << "bh[1]=" << bh[i] << endl;
	i = 2;
	cout << "bh[2]=" << bh[i] << endl;
}

image-20240610215710860

将上述代码继续优化

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

int main()
{
	//创建数组
	int bh[3];  //编号
	string name[3]; //姓名

	//可以通过数组下表访问数组元素,数组下标从0开始.
	//数组中的每个元素特征和使用方法与单个变量完全相同

	for (int i = 0; i < 3; i++)  //i要小于数组长度
	{
		bh[i] = 30 + i;  //循环第0次,i的值是0,编号是30  循环第1次,i的值是1 编号是31 循环第二次,i的值是2 编号是32
	}
	/*int i;

	i = 0;
	cout << "bh[0]=" << bh[i] << endl;
	i = 1;
	cout << "bh[1]=" << bh[i] << endl;
	i = 2;
	cout << "bh[2]=" << bh[i] << endl;*/
	//使用for循环改写
	for (int i = 0; i < 3; i++)
	{
		cout << "bh[" << i << "]=" << bh[i] << endl;
	}
}

image-20240610220103572

2、数组的使用

可以通过下标访问数组中的元素,数组下标从0开始

数组中每个元素的特征和使用方法与单个变量完全相同

语法:数组名[数组下标]

3、数组占用内存的情况

用sizeof(数组名)可以得到整个数组占用内存空间的大小(只适用于C++基本数据类型)

#include <iostream>  //包含的头文件

using namespace std;  //指定缺省的命名空间

int main()
{
	//创建数组
	int bh[3];  //编号
	string name[3]; //姓名

	cout << "数组bh占用的内存空间是:" << sizeof(bh) << endl;

}

image-20240610220906696

4、数组的初始化

声明的时候初始化

数据类型 数组名[数组长度] ={值1,值2, ......}

数据类型 数组名[] ={值1,值2,.......}

数据类型 数组名[数组长度] = {0};//把全部元素初始化为0

数据类型 数组名[数组长度] = { };//把全部元素初始化为0

13、一维数组的越界

#include <iostream>

using namespace std;

int main()
{
	//定义一维数组
	int a[5] = { 3,6,9,5,8 };

	//用数组表示法操作数组
	/*cout << "a[0]的值是:" << a[0] << endl;
	cout << "a[1]的值是:" << a[1] << endl;
	cout << "a[2]的值是:" << a[2] << endl;
	cout << "a[3]的值是:" << a[3] << endl;
	cout << "a[4]的值是:" << a[4] << endl;*/
	//使用for循环优化代码
	for (int i = 0; i < 5; i++)
	{
		cout << "a[" << i << "]的值是:" << a[i] << endl;
	}
	cout << endl;

	//用指针表示法操作数组
	int* p = a;
	/*cout << "*(p+0)的值是:" << *(p + 0) << endl;
	cout << "*(p+1)的值是:" << *(p + 1) << endl;
	cout << "*(p+2)的值是:" << *(p + 2) << endl;
	cout << "*(p+3)的值是:" << *(p + 3) << endl;
	cout << "*(p+4)的值是:" << *(p + 4) << endl;*/
	//使用for循环优化代码
	for (int i = 0; i < 5; i++)
	{
		cout << "*(p+" << i << ")的值是:" << *(p + i) << endl;
	}
}

14、解释器和编译器有什么不同?

解释器:解释器一种对代码(或者字节码)进行解释并执行相应的操作的工具;编译器将代码作为输入,并生成目标文件。就C++而言,编译和链接后,将得到一个可执行文件,处理器可直接执行它,而无需做进一步解释

编译器:将C++代码文件作为输入,并生成一个使用机器语言的目标文件。通常代码依赖与库和其他代码文件中的函数。

15、链接器的作用

将编译器生成的目标文件和库文件链接在一起,生成最终的可执行文件或者共享库

16、正常的开发周期包括哪些步骤

编写代码-->通过编译创建目标文件-->通过链接创建可执行文件-->执行应用程序一边进行测试-->调试-->修复代码中的错误并重复这些步骤

17、一维数组的排序

//1.如果函数的返回值<0, 那么p1所指向元素的会被排在p2所指向元素的前面
//2.如果函数的返回值==0, 那么p1所指向的元素与p2所指向的元素的顺序不确定
//3.如果函数的返回值>0, 那么p1所指向的元素会被排在p2所指向元素的后面

//qsort()函数用于各种数据类型的数组进行排序
//函数的原型:
// void qsort(voidbase,size_t number,size_t size,int(compar)(const void ,const void));

#include <iostream> //包含头文件

using namespace std;  //指定缺省的命名空间

//1.如果函数的返回值<0, 那么p1所指向元素的会被排在p2所指向元素的前面
//2.如果函数的返回值==0, 那么p1所指向的元素与p2所指向的元素的顺序不确定
//3.如果函数的返回值>0,  那么p1所指向的元素会被排在p2所指向元素的后面

//qsort()函数用于各种数据类型的数组进行排序
	//函数的原型:
	// void qsort(void*base,size_t number,size_t size,int(*compar)(const void *,const void*));

//声明回调函数
int compasc(const void* p1, const void* p2);

int main()
{
	//声明一个整i型数组
	int a[8] = { 4,2,7,5,8,6,1,3 };

	//函数的原型:
	// void qsort(void*base,size_t number,size_t size,int(*compar)(const void *,const void*));
	//回调函数的调用
	qsort(a, sizeof(a) / sizeof(int), sizeof(int), compasc);

	//显示数组内容
	for (int i = 0; i < 8; i++)
	{
		//cout << "a[" << i << "]的值是: " << *(a + i) << endl;
		cout << "a[" << i << "]的值是: " << a[i] << endl;
	}

	return 0;
}

//回调函数的定义:即回调函数实现过程
int compasc(const void* p1, const void* p2)
{
	/*if (*((int*)p1) < *(int*)p2)
		return -1;
	if (*(int*)p1 == *(int*)p2)
		return 0;
	if (*(int*)p1 > *(int*)p2)
		return 1;*/
	return *((int*)p1) - *((int*)p2);  //等同于边代码
}

image-20240624210533803