C++基本语法的知识体系

参考网址:C++基础入门

几个理解的知识点

1.变量,变量类型,变量名的作用
答:
变量:是用来存放各种数据类型的容器,是一段内存空间。程序中定义了一个变量,就等于程序向内存条申请了一段存储空间。
变量类型:是为了指定多大的内存空间分配给变量,如整型,浮点型,字符型,字符串型,布尔型等。不同变量类型的变量所占用的内存大小是不一样的。
变量名:是给一段内存空间命名,这样就不需要内存空间的物理地址,直接通过变量名,访问内存空间存储的数据,简化操作。
常量:是变量的特殊形式,只是内存空间中的值不能修改。

2.数据类型存在的意义
答:
给变量分配合适的内存空间,如整型,浮点型,字符型,字符串型,布尔型等数据类型的变量所占用的内存空间是不同的。
其中字符型变量、字符串型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元。而布尔类型,true存储的是1,false存储的是0。

3.数据类型和数据结构
答:
数据类型:简单数据类型有整型,浮点型,字符型,字符串型,布尔型;复杂数据类型有结构体、类
数据结构:变量是最简单的一种数据存储结构;数组也是一种数据结构;线性表、树、队列等都是数据结构。容器如vector、list、deque、set、map等都是各种数据结构,用来存放数据。

	注:
	数据结构,强调数据之间的关系,代表一种数据的存储结构,如树,队列,列表,字典等。
	数据类型,强调合法的操作,如对字符串,数字可以进行什么样的操作。

4.cin和cout
答:
cin相当于C语言中的scanf函数,用于用户输入数据;
cout相当于C语言中的print函数,用于打印输出数据;

	cin >> a; //表示用户输入的数字,存储到变量a中。
	cout  << "当前输入为:"  <<  a << endl;  //表示打印a的值。

5.代码注释

单行注释:// 描述信息 (通常放在一行代码的上方,或者一条语句的末尾,对该行代码解释)
多行注释: /* 描述信息 */ (通常放在一段代码的上方,对该段代码做整体解释)

从七个方面理解C++基本语法的知识体系:

数据类型、运算符、程序流程控制、数组、函数、指针、结构体

一、数据类型

整型:short、int(4)、long、long long
答:
整型所占内存空间大小,因操作系统的种类和位数不同而有所区别。
在这里插入图片描述
注意:
硬件的64位和32位,指的是CPU位宽,即CPU可以处理的数据比特数。
软件的64位和32位,指的是程序指令的位宽,包括操作系统的位数,也是我们经常提到的32位和64位含义。

浮点型:float(4)、double(8)
字符型:char(1)
字符串型:字符数组、字符指针、string类
布尔型:bool(1)

二、运算符

算术运算符、赋值运算符、比较运算符、逻辑运算符

三、程序流程控制(逻辑控制)

1.顺序结构

从程序入口开始,程序一步一步顺序执行。

2.选择结构

1)if语句

if
if —else
if—else if—else
嵌套if(多层if语句)

2)三目运算符

c = (a > b ? a : b)
三目运算符返回的是变量,可以继续赋值。

3)switch语句

switch(表达式)
{

	case 结果1:执行语句;break;

	case 结果2:执行语句;break;

	...
	default:执行语句;break;
}

注意1:switch语句中表达式类型只能是整型或者字符型

注意2:case里如果没有break,那么程序会一直向下执行

总结:与if语句比,对于多条件判断时,switch的结构清晰,执行效率高,缺点是switch不可以判断区间,即case后面的结果只能是整型或字符型。

3.循环结构

1)while循环:

while(循环条件)
{ 
	循环语句
}

注意:
当写成while(1)或者while(true)时,会陷入死循环,程序将一直循环执行。
当写成while(num)时,num如果为0,表示假,条件不成立,退出此循环;当num不为0,表示真,会一直循环执行。
可以使用break语句退出当前循环,包括可以退出死循环。

2)do … while循环:

do
{
循环语句 
 } while(循环条件);

注意:与while循环的区别在于,do…while会先执行一次循环语句,再判断循环条件。

3)for循环:

for(起始表达式;条件表达式;末尾循环体) 
{
	循环语句;
}

注意:
起始表达式只执行一次;
执行顺序是先判断条件表达式,再执行循环语句,最后执行末尾循环体,再判断条件表达式…

如:

 for (int i = 0; i < 10; i++)//这里i++和++i没有区别
{
	cout << i << endl;
}

4)嵌套循环:

外层循环执行一次,内层循环执行一周。

4.补充

1) break语句:用于跳出选择结构或者循环结构

break使用的时机:

出现在switch条件语句中,作用是终止case并跳出switch
出现在循环语句中,作用是跳出当前的循环语句
出现在嵌套循环中,跳出最近的内层循环语句

2)continue语句

用在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环。
注意:continue并没有使整个循环终止,而break会跳出循

3)goto语句:可以无条件跳转语句

使用语法: goto 标记;
(如果标记的名称存在,执行到goto语句时,会跳转到标记的位置

四、数组

所谓数组,就是一个集合,里面存放了相同类型的数据元素。
(数组是一种特殊的容器,用于存储数据。数组(Array)是一种线性表数据结构)

特点1:数组中的每个数据元素都是相同的数据类型

特点2:数组是由连续的内存位置组成的

特点3:数组名是给一段连续的内存空间起个名字,数组中的元素通过索引得到。

特点4:数组名是一个常量,不可以再次修改。数组中的元素是变量,可以进行修改。

特点5:每一次程序运行时,都会重新给程序分配内存空间,从而每次内存地址都是不同的。一个字节为一个地址;占多个字节的变量,用首字节的地址表示。
注:数组可以直接作为函数参数,也可以用数组名(地址)作为函数参数

1.一维数组名称的用途

sizeof(array):可以统计整个数组在内存中的长度,即统计数组占据多少个字节空间。
sizeof(array[0]):查看数组中第一个元素的内存所占大小
cout << array:可以获取数组在内存中的首地址
cout << &array[0]:查看数组的第一个元素的物理地址

注意:冒泡排序法
在这里插入图片描述
对9个数字进行冒泡排序:
在这里插入图片描述

2.二维数组名称的用途

查看二维数组所占内存空间,
获取二维数组首地址。
注意:二维数组名就是这个数组的首地址,二维数组的某一行构成一维数组,可以直接得到某一行的首地址。对于一个具体的数组元素,需要用&取地址符号。

//二维数组数组名
int arr[2][3] ={{1,2,3},{4,5,6}};

cout << "二维数组大小: " << sizeof(arr) << endl;
cout << "二维数组一行大小: " << sizeof(arr[0]) << endl;
cout << "二维数组元素大小: " << sizeof(arr[0][0]) << endl;

cout << "二维数组行数: " << sizeof(arr) / sizeof(arr[0]) << endl;
cout << "二维数组列数: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;

//地址
cout << "二维数组首地址:" << arr << endl;
cout << "二维数组第一行地址:" << arr[0] << endl;
cout << "二维数组第二行地址:" << arr[1] << endl;

cout << "二维数组第一个元素地址:" << &arr[0][0] << endl;
cout << "二维数组第二个元素地址:" << &arr[0][1] << endl;

五、函数

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

1.函数定义

在这里插入图片描述

2.函数调用

使用已经定义好的函数,调用函数时,实参会传递给形参。(值传递时,如果形参发生改变,并不会影响实参)

使用语法:函数名(实参)
内存解释过程:
在这里插入图片描述
在这里插入图片描述
函数调用过程中,实参a,b自始至终没有发生变化,形参num1,num2发生了变换,但形参变化不影响实参。

3.函数声明

有了函数声明,被调用函数可以定义在主函数后面,不需要一定放在前面。

作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数的声明可以多次,但是函数的定义只能有一次

4.函数的分文件编写

让代码结构更加清晰

函数分文件编写一般有4个步骤:
1)创建后缀名为.h的头文件
2)创建后缀名为.cpp的源文件
3)在头文件中写函数的声明
4)在源文件中写函数的定义
5)关联.h头文件和.cpp源文件
6)引用.h头文件到当前程序即可。

六、指针

1.指针的定义和使用

1)指针就是地址,保存着变量a表示的内存空间的地址编号。

注:指针和指针变量的区别
“指针”是概念,指针就是地址,地址就是指针。(地址就是内存单元的编号)
“指针变量”是具体实现指针变量我们一般简称指针,它是一个变量,所以需要进行定义。指针变量是用来存放另一个变量的地址(即指针),显然,指针变量的值改变了,那么其指向的值就变了。
在这里插入图片描述
例如:a是整型变量,值为10;
p为指针变量,值为变量a表示的内存空间的地址,所以p=&a。
由于p也是一块内存空间,同样有地址编号,即&p;
*p表示以p内存空间的内容为地址,寻址得到p地址内存空间保存的内容,即 *p=a。
(指针变量定义语法: 数据类型 * 变量名;
这里面的“数据类型”表示指针指向的内容,它的数据类型。指向的值是整型数字,这里就是int;指向的值是字符,就是char;指向的值是实数,这里就是float或者为double)
在这里插入图片描述

2)指针变量和普通变量的区别

定义变量等于申请一块内存空间,一块内存空间有名字(变量名),也有编号(地址),也有存储的内容(数据)。

普通变量存放的是数据,指针变量存放的是地址
指针变量可以通过" * "操作符,操作指针变量指向的内存空间,这个过程称为解引用

总结1: 我们可以通过 & 符号 获取变量的地址

总结2:利用指针可以记录地址

总结3:对指针变量解引用" * ",可以操作指针指向的内存。
如果不是指针变量,就不能对其进行 " * "操作,所以我们必须先定义一个指针变量,即int * p;表示定义了一个变量,其是指针变量,后面可以使用 解引用操作,并且这个指针变量的数据类型是整型,即p的内容为整型。

3.指针所占内存空间

提问:指针也是种数据类型,那么这种数据类型占用多少内存空间?
在这里插入图片描述

4.空指针和野指针

空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
在这里插入图片描述
野指针:指针变量指向非法的内存空间

总结:空指针和野指针都不是我们申请的空间,因此不要访问。

5.const修饰指针

作用:是限定指针的指向和指针指向的内容,指针的指向是指针变量p保存的内容,即地址;指针指向的内容是以地址(指针的指向)来寻址得到的内容。普通指针可以修改指针的指向和指针指向的内容,而const修饰的指针,不能随意修改这两个东西。

const修饰指针有三种情况:

const修饰指针 — 常量指针,即某个常量的指针,表示指针指向的值是个常量,即指针指向的内容不可以更改,但指针本身值可以更改
const修饰常量 — 指针常量,表示这个指针是个常量,即指针本身值不可以更改,但指针指向的内容可以更改
const即修饰指针,又修饰常量 — 常量指针 + 指针常量

1)const修饰指针 — 常量指针
答:
就是某个常量的指针,表示指针指向的值是个常量,即指针指向的内容不可以更改,但指针本身值可以更改

const int * p = &a;   const限制了 *,带*操作不能被直接修改,如*p=20

常量指针表示*p是一个常量了,即指针p指向的内容是一个常量,不能修改,但p本身是个变量,可以修改。

在这里插入图片描述

重点:虽然不能直接修改* p,但通过改变p的值,* p自然就改变了

//1.常量指针
void test01()
{
int a = 10;
int b = 10;
int c = 20;

const int *p = &a;

cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

//更改指针p的值,但指针p指向的值不发生改变
p = &b; //指针p的值变了,表示其指向的内存地址发生了变化,但是内存中的值没有发生变化。(指针p的值原来是0x0011内存,现在是0x0022内存,但两块内存中存储的值是相同的)
cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

//更改指针p指向的值,但指针p的值不发生改变
//*p = 10;  //不允许修改,指针p指向的值是常量

//更改指针p的值,同时更改指针p指向的值
p = &c;
cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

}

2)const修饰常量 — 指针常量
答:
表示这个指针是个常量,即指针本身值不可以更改,但指针指向的内容可以更改

在变量p前,加const进行修饰,从而p变成常量;
所以const修饰常量这句话表示是,加入const后,原来的变量p变成常量了,注意此时p还不认为是指针类型的变量,因为还没加int*.
又当因为前面有int*,表示的是指针变量,从而叫指针常量。

int * const p = &a,即const p看成常量。const限制了p,p不允许直接修改,如p = &b

指针常量,很显然,p是一个常量了,那么p的内容是不允许修改的,但指针常量p所指向的值是可以修改的,就地址不变,但地址所对应的数据可以变。(这个也是可以理解的,变量a的地址不能变,但a的值可以变)

在这里插入图片描述
重点:
虽然不能直接修改p的值,那能不能通过修改p指向的值,使得p的值也自然就改变了呢?
注意,这是错误的,通过修改p指向的值,不会改变p本身的值,它不像常量指针那样,可以通过更改指针的值,达到更改“指针指向的值”这个目的。根本原因是指针是因,指针指向的值是果,不能通过改变结果来影响原因,但可以通过更改原因来产生不同的结果

//指针常量
void test02()
{
int a = 10;
int b = 10;
int c = 20;

int * const p = &a;

cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

//更改指针p指向的值,但指针p的值不发生改变
*p = c;
cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

//更改指针p的值,但指针p指向的值不发生变化
//p = &b; //不允许修改,指针p的值是一个常量
}

3)const即修饰指针,又修饰常量
答:
就是常量指针+指针常量。

在指针int*前,加入const修饰;在变量p前,也加入const修饰。表示这个指针的指向,和这个指针指向的内容,都被固定死,都不允许修改了。
在这里插入图片描述

//常量指针+指针常量
void test03()
{
int a = 10;
int b = 10;
int c = 20;

const int * const p = &a;
cout << "指针p的值:" << p << endl;
cout << "指针p指向的值:" << *p << endl;

//更改指针p的值,但指针p指向的值不发生改变
//p = &b;//不允许修改,指针p的值是一个常量

//更改指针p指向的值,但指针p的值不发生变化
//*p = c;//不允许修改,指针p指向的值是常量

}

6.指针和数组

作用:利用指针访问数组中元素
在这里插入图片描述

7. 指针和函数

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

(下图内存条的演示中,p1和p2应该为p1和p2)
在这里插入图片描述
总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递

8 指针、数组、函数

就是通过指针,将数组作为函数中的参数,进行传递。因为函数中的参数通常为一个单值,而数组为一连串值,此时需要地址来传递,因而用到指针。

七、结构体

一种特殊的数据类型,它的使用类似于整型、字符型等数据类型,但不像int、char等数据类型是C++自带的,结构体需要我们自己定义,所以需要将复杂概念,简单理解。

创建一个结构体变量,理解就是创建一个变量,数据类型是结构体。
创建一个结构体数组,理解就是创建一个数组,数据类型是结构体。
创建一个结构体指针,理解就是创建一个指针,数据类型是结构体,因为指向的值的数据类型是结构体。

总结:结构体属于用户自定义的数据类型,允许用户存储不同的数据类型,所以结构体是一种数据类型。

1.结构体定义和使用

定义一个结构体,就是在定义一种新的数据类型。
语法:struct 结构体名 { 结构体成员列表 };
在这里插入图片描述

通过结构体创建变量的方式有三种:创建一个结构体变量,就是在创建一个变量,它的数据类型是结构体。

1)struct 结构体名 变量名
struct Student s1;类似于int a,只不过这里变量s1的数据类型是结构体。
在这里插入图片描述
2)struct 结构体名 变量名 = { 成员1值 , 成员2值…}
在这里插入图片描述
3)定义结构体时顺便创建变量:一般不使用
在这里插入图片描述
在这里插入图片描述

总结1:定义结构体时的关键字是struct,不可省略

总结2:创建结构体变量时,关键字struct可以省略
(区别:结构体是一种数据类型,结构体变量是一种变量,数据类型是结构体。)

总结3:结构体变量利用操作符 ‘’.’’ 访问成员

2.结构体数组

数组中的元素都是结构体类型

语法:struct 结构体名 数组名[元素个数] = { {} , {} , … {} }
在这里插入图片描述
在这里插入图片描述

3.结构体指针

通过指针访问结构体中的成员

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

下图中,指针的数据类型是结构体,因为其“指向的值”的数据类型是结构体。好比“指向的值”的数据类型是整型,那么指针的数据类型也应该是整型。
在这里插入图片描述

4.结构体嵌套结构体

作用: 结构体中的成员可以是另一个结构体
在这里插入图片描述
结构体嵌套结构体:定义和使用
在这里插入图片描述
在这里插入图片描述

5.结构体做函数参数

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

传递方式有两种:值传递,地址传递

理解就是将结构体变量作为函数参数,如同可以将一个整型变量作为一个函数参数,同样分为值传递和地址传递。(具体原理参考函数章节)
1)先定义结构体,再定义一个结构体变量。
2)值传递时,将结构体变量作为函数参数。
3)地址传递时,将结构体指针作为函数参数,其中这个结构体指针指向的值为结构体变量。
注:如果不想修改主函数中的数据(实参),用值传递,反之用地址传递。

示例:

//学生结构体定义
struct student
{
//成员列表
string name;  //姓名
int age;      //年龄
int score;    //分数
};

//值传递
void printStudent(student stu )
{
stu.age = 28;
cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;
}

//地址传递
void printStudent2(student *stu)
{
stu->age = 28;
cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age  << " 分数:" << stu->score << endl;
}

int main() {

student stu = { "张三",18,100};
//值传递
printStudent(stu);
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl;

cout << endl;

//地址传递
printStudent2(&stu);
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;

system("pause");

return 0;
}

6.结构体中 const使用场景

作用:用const来防止误操作
原理:值传递时,结构体变量作为函数参数,需要实参数据全部复制到函数中,内存占用大。
而地址传递时,结构体指针作为函数参数,传入的只是一个地址,内存占用小;但是,地址传递时,子函数变化可能会导致主函数中的实参数据变化;为了不让此种情况发生,引入const,来约束子函数的形参,使其为常量结构体指针,从而不能修改结构体指针指向的值。(常量指针,不允许修改指针指向的值)
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值