当前位置: 首页 > article >正文

初阶C++笔记第一篇:C++基础语法

虽然以下大多数知识点都在C语言中学过,但还是有一些知识点和C语言不同,比如:代码格式、头文件、关键字、输入输出、字符串类型等...

1. 初识C++

1.1 第一个C++程序

编写C++分为4个步骤:

  • 创建项目
  • 创建文件
  • 编写代码
  • 运行程序

C++的第一条程序:

#include<iostream>
using namespace std;int main()
{cout << "hello world" << endl;//输出语句system("pause");//按任意键才继续执行return 0;
}

运行程序:

cout是由I/O流库定义的对象

在C++编程语言中,cout 是一个用于在计算机屏幕上显示信息的对象。它是 iostream 类型的对象,属于C++的输入输出流库。C++的输出是通过“流”(stream)的方式实现的,流运算符的定义等信息存放在C++的输入输出流库中。因此,如果在程序中使用 cout 和流运算符,就必须使用预处理命令将头文件 iostream 包含到本文件中,即 #include <iostream>

C++中endl的作用

在C++中,endl是一个操纵符(manipulator),用于在输出流中插入换行符并刷新输出缓冲区。它的作用不仅仅是换行,还包括将缓冲区的内容立即显示出来,也叫做缓冲流冲刷

说白了endl就是作为输出语句结尾需要将剩余的需要输出的值输出并在最后加个换行符' \n '。

1.2 注释

作用:在代码中加一些说明和解释,方便自己或其他程序员阅读代码

两种格式:

1.单行注释:/ /  描述信息

通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明

2.多行注释:/* 描述信息 */

通常放在一段代码的上方,对该段代码做整体说明

提示:编译器在编译代码时,会忽略注释的内容

1.3 变量

作用:给一段指定的内存空间起名,方便操作这段内存

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

示例:

#include<iostream>
using namespace std;int main()
{int a = 10;//创建变量cout <<"a = "<<a<< endl;//输出变量system("pause");//按任意键才继续执行return 0;
}

1.4 常量

作用:用于记录程序中不可更改的数据

C++定义常量两种方式:

1. #define 宏常量:#define  常量名  常量值

通常在文件上方定义,表示一个常量

2. const修饰的变量:const  数据类型  常量名  =  常量值

通常在变量定义前加关键字const,修饰该变量为常量,不可修改。

示例:

#include<iostream>
using namespace std;
//1、宏常量
#define day 7
int main()
{cout << "一周里总共有" << day << "天" << endl;//day = 8; 对常量进行赋值会报错//2、const修饰常变量const int month = 12;cout << "一年里总共有" << month << "月" << endl;//month = 13; 对const修饰的常变量赋值会报错system("pause");//按任意键才继续执行return 0;
}

运行程序:

1.5 关键字

作用:关键字是C++中预先保留的单词(标识符)

  • 在定义变量或者常量的时候,不要用关键字(不要撞名)
asmdoifreturntypedef
autoduobleinlineshorttypeid
booldynamic_castintsignedtypename
breakelselongsizeofunion
caseenummutablestaticunsigned
catchexplicitnamespacestatic_castusing
charexportnewstructvirtual
classexternoperatorswitchvoid
constfalseprivatetemplatevolatile
const_castfloatprotectedthiswchar_t
continueforpublicthrowwhile
defaultfriendregistertrue
deletegotoreinterpret_casttry

统计:C++总共有63个关键字

提示:在给变量或者常量起名称时,不要用C++的关键字,否则会产生歧义。

1.6 标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则

  • 标识符不能是关键字
  • 标识符只能由字母、数字、下划线组成
  • 第一个字符必须为字母或下划线
  • 标识符中字母区分大小写

建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读

2. 数据类型

C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存

2.1 整型

作用:整型变量表示的是整型类型的数据

C++中能够表示整型的类型有以下几种方式,区别在于所占内存空间不同:

数据类型占用空间取值范围
short(短整型)2字节(-2^15 ~ 2^15-1)
int(整型)4字节(-2^31 ~ 2^31-1)
long(长整型)Windows为4字节,Linux为4字节(32位),8字节(64位)(-2^31 ~ 2^31-1)
long long(更长整型)8字节(-2^63 ~ 2^63-1)

2.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存大小

语法:sizeof(数据类型 / 变量);

示例:

#include<iostream>
using namespace std;int main()
{cout << "short 类型所占空间为:" << sizeof(short) << endl;cout << "int 类型所占空间为:" << sizeof(int) << endl;cout << "long 类型所占空间为:" << sizeof(long) << endl;cout << "long long 类型所占空间为:" << sizeof(long long) << endl;system("pause");//按任意键才继续执行return 0;
}

运行代码:

2.3 实型(浮点型)

作用:用于表示小数

浮点型变量分为两种:

  1. 单精度float
  2. 双精度double

两者的区别在于表示的有效数字范围不同

数据类型

占用空间有效数字范围
float4字节7位有效数字
double8字节15 ~ 16位有效数字

示例:

#include<iostream>
using namespace std;int main()
{float f1 = 3.1415926f;double d1 = 3.1415926;cout << f1 << endl;cout << d1 << endl;//科学计数法表示小数//E后面如果是正数就代表10,如果是负数就代表0.1float f2 = 3E2;//3 * 10 ^ 2float f3 = 3E-2;//3 * 0.1 ^ 2cout << "f2= " << f2 << endl;cout << "f3= " << f3 << endl;system("pause");//按任意键才继续执行return 0;
}

运行代码:

我们只需要知道有这种科学计数法的格式,知道有这个表达式,以后见到不会懵。

为什么float变量后面需要额外加一个f ? 为什么最后double变量和float变量输出小数点后面的有效数字默认都是5个?

  1. 因为所有小数默认为double类型,所以给float类型赋值小数时后面加一个 f 将小数转换成float类型
  2. 因为输出最多只能表示6位有效数字,如果要看全部的有效数字需要额外的配置,我们现在还接触不到 

2.4 字符型

作用:字符型变量用于显示单个字符

语法:char  ch  =  'a';

注意1:在现实字符型变量时,用单引号将字符括起来,不要用双引号

注意2:单引号内只能有一个字符,不可以是字符串

  • C和C++中字符型变量只占用1个字节
  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元

示例:

#include<iostream>
using namespace std;int main()
{//1.创建字符char ch = 'a';cout << ch << endl;//2.字符和字符变量的大小cout<< "char字符型变量所占内存大小: " << sizeof(ch) << endl;//3.打印字符的ASCII码值//将字符变量ch的值'a'强制类型转换成int类型便可以得到ASCII码值cout << "字符" << ch << "的ASCII码值为: " << (int)ch << endl;system("pause");//按任意键才继续执行return 0;
}

代码运行:

ASCII码表:

ASCII码大致由以下两部分组成:

  1. ASCII非打印控制字符(控制字符):ASCII表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。
  2. ASCII打印字符(可显示字符):数字 32-126 分配给了能在 键盘上找到的字符,当查看或打印文档是就会出现。

可显示字符

可显示字符编号范围是32-126(0x20-0x7E),共95个字符。

控制字符

ASCII控制字符的编号范围是0-31和127(0x00-0x1F和0x7F),共33个字符。

2.5 转义字符

作用:用于表示一些不能显示出来的ASCII字符

现阶段我们常用的转义字符有: \n   \\    \t 

转义字符列表:

  • \?:在书写连续多个问号时使用,防止他们被解析成三字母词,在新的编译器上无法验证
  • 三字母词就是??)--转换-->],??(--转换-->[
  • \':用于表示字符常量'
  • \":用于表示字符串内部的双引号
  • \\:用于表示反斜杠,防止字符被解释为转义字符
  • \a:警报(蜂鸣)
  • \b:退格键,光标回退一个字符,但不删除字符
  • \f:换页符,光标移到下一页,在现代系统上,这已经反应不出来了,行为改成类似于\v
  • \n:换行符
  • \r:回车符,光标移到同一行的开头
  • \t:制表符,光标移到下一个水平制表位,通常是下一个8的倍数
  • \v:垂直分隔符,光标移到下一个垂直制表位,通常是下一行的同一列。
  • 下面两种转义可以理解为:字符的8进制或16进制的形式
  • \ddd:ddd表示1—3个八进制的数字。  如:\130   表示字符X
  • \xdd:dd表示2个十六禁止的数字。    如:\x30   表示字符0

示例:

#include<iostream>
using namespace std;int main()
{//换行符'\n'cout << "hello world\n";//反斜杠'\\'cout << "\\" << endl;//水平制表符'\t'cout << "aaaa\thelloworld" << endl;cout << "aa\thelloworld" << endl;cout << "aaaaaa\thelloworld" << endl;system("pause");//按任意键才继续执行return 0;
}

运行结果:

cout << "hello world\n";

因为endl的作用也是换行,所以一般情况下后面没有endl也没有什么问题,如果没有endl就不会换行,下一次使用cout输出不会在当前语句的下一行输出,而是在当前语句的末尾输出。

2.6 字符串类型

作用:用于表示一串字符

两种风格

1. C风格字符串:char  变量名[ ]  =  "字符串值";

示例:

#include<iostream>
using namespace std;int main()
{char str[] = "hello world";cout << str << endl;system("pause");//按任意键才继续执行return 0;
}

运行代码:

注意:C风格的字符串要用双引号括起来

2. C++风格字符串:string  变量名  =  "字符串值";

示例:

#include<iostream>
#include<string>
using namespace std;int main()
{string str = "hello world";cout << str << endl;system("pause");//按任意键才继续执行return 0;
}

注意:C++风格字符串需要加入头文件 include<string> 

#include<iostream>
#include<string>
using namespace std;int main()
{char str1[20];str1 = "hello world";//报错string str2;str2 = "hello world";//不会报错cout << str2 << endl;system("pause");//按任意键才继续执行return 0;
}

还要注意如果用char[ ]的方式开辟一块存储字符串的变量也就是字符数组str1,当给str1直接赋值一串字符串时会报错,因为这里的str1是首元素地址,是数组,所以给一个地址再赋值一个地址就会报错。

而char*是一个指针,string是一个类,内部封装了char * ,管理这个字符串,是一个char *型的容器

总结:

  1. char[ ]类型是一个字符数组类型,所以数组名str1就是首元素地址。
  2. string本质上是一个类封装了char*,也就是相当于char*,可以直接赋值"hello world"常量字符串,因为是将这个常量字符串的首字符地址赋值给了string变量,所以str2相当于一个字符指针变量。

注意:string不能完全等同于char*,因为string本身就是一个类,就是封装了char*使用这个类型存储地址,但是不能直接给string这个类赋值NULL,因为它不完全是一个char*,这个类只能存储字符串。

2.7 布尔类型 bool

作用:布尔数据类型代表真或假的值

bool类型只有两个值:

  • true --- 真(本质是1)
  • false ---假(本质是0)

注意:理论上在C++里布尔0可以表示假false,其他非0的值都能表示真true

bool类型占1个字节大小

示例:

#include<iostream>
#include<string>
using namespace std;int main()
{bool flag = true;cout << flag << endl;//1flag = false;cout << flag << endl;//0cout << "size of bool= " << sizeof(bool) << endl;//bool类型大小为1system("pause");//按任意键才继续执行return 0;
}

运行代码:

2.8 数据的输入

作用:用于从键盘上获取数据

关键字:cin

语法:cin  >>  变量

示例:

#include<iostream>
#include<string>
using namespace std;int main()
{//整型输入int a = 0;cout << "请给整型变量a赋值:>";cin >> a;cout << "整型变量a = " << a <<endl;//字符型输入char c = 'a';cout << "请给字符变量c赋值:>";cin >> c;cout << "字符变量c = " << c << endl;//浮点型输入double d = 0.0;cout << "请给浮点变量d赋值:>";cin >> d;cout << "浮点变量d = " << d << endl;//字符串类型输入string str = "hello";cout << "请给字符串类型变量str赋值:>";cin >> str;cout << "字符串类型变量str = " << str << endl;//布尔类型输入bool flag = true;cout << "请给布尔类型变量flag赋值";cin >> flag;cout << "布尔类型变量flag = " << flag << endl;system("pause");//按任意键才继续执行return 0;
}

代码运行:

3. 运算符

作用:用于执行代码的运算

本章我们主要讲解一下几类运算符:

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

3.1 算术运算符

作用:用于处理四则运算

算术运算符包括:+、-、*、/、%、前置++、后置++、前置--、后置--、正号+、负号-

3.2 赋值运算符

作用:用于将表达式的值赋值给变量

赋值运算符包括:=、+=、-=、*=、/=、%=

3.3 比较运算符

作用:用于表达式比较,并返回一个真值或假值

比较运算符包括:>、<、>=、<=、==、!=

3.4 逻辑运算符

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

逻辑运算符有以下符号:

运算符术语示例结果
!a如果a为假,则!a为真;如果a为真,则!a为假
&&a && b如果a和b都为真,则结果为真,否则为假
| |a  | |  b如果a和b有一个为真,则结果为真,二者都为假时,结果为假

4. 程序流程结构

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

  • 顺序结构:程序按顺序执行,不发生跳转
  • 选择结构:依据条件是否满足,有选择的执行相应功能
  • 循环结构:依据条件是否满足,循环多次执行某段代码

4.1 选择结构

4.1.1 if语句

作用:执行满足条件的语句

if语句的三种形式

  • 单行格式if语句
  • 多行格式if语句
  • 多条件的if语句

1. 单行格式if语句:if(条件){条件满足执行的语句}

2. 多行格式if语句:if(条件){条件满足执行的语句}else{条件不满足执行的语句}

3. 多条件的if语句:if(条件1){条件1满足执行的语句}else if(条件2){条件2满足执行的语句}... else{都不满足执行的语句}

嵌套if语句:在if语句中,可以嵌套使用if语句,达到更精准的条件判断

案例需求:

  • 提示用户输入一个高考考试分数,根据分数做如下判断
  • 分数如果大于600分视为考上一本,大于500分考上二本,大于400分考上三本,其余视为未考上本科;
  • 在一本分数中,如果大于700分,考入北大,大于650分,考入清华,大于600考入人大。

示例:

#include<iostream>
#include<string>
using namespace std;int main()
{int score = 0;cout << "请输入分数:" << endl;cin >> score;if (score > 600) {cout << "恭喜你,考入了一本" << endl;if (score > 700) {cout << "考上了北京大学" << endl;}else if (score > 650) {cout << "考上了清华大学" << endl;}else {cout << "考上了人民大学" << endl;}}else if(score > 500) {cout << "恭喜你,考入了二本" << endl;}else if (score > 400) {cout << "恭喜你,考入了三本" << endl;}else {cout << "为考入本科,还请再接再厉" << endl;}system("pause");//按任意键才继续执行return 0;
}

4.1.2 三目运算符

作用:通过三目运算符实现简单的判断

语法: 表达式1 ? 表达式2 : 表达式3 

解释:

如果表达式1的值为真,执行表达式2,并返回表达式2的结果;

如果表达式1的值为假,执行表达式3,并返回表达式3的结果;

示例:

#include<iostream>
#include<string>
using namespace std;int main()
{int a = 10;int b = 20;int c = 0;c = a > b ? a : b;cout << "c = " << c << endl;//C++中三目运算符返回的是变量,可以继续赋值(a > b ? a : b) = 100;cout << "a = " << a << endl;cout << "b = " << b << endl;
}

注:三目运算符返回的是变量,可以对其进行赋值

4.1.3 switch语句

作用:执行多条件分支语句

语法:

switch(整型或整型表达式)
{case 结果1(常量或常量表达式): 执行语句; break;case 结果2(常量或常量表达式): 执行语句; break;...default: 执行语句; break;
}

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

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

注意3:与if语句比,对于多条件判断时,switch的结构清晰,执行效率高,缺点是switch不可以判断区间

4.2 循环结构

4.2.1 while循环语句

作用:满足循环条件,执行循环语句

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

解释:只要循环条件的结果为真,就执行循环语句

4.2.2 do while循环语句

作用:满足循环条件,先执行循环语句

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

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

4.2.3 for循环语句

作用:满足循环条件,执行循环语句

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

详解:

注意:for循环中的表达式,要用分号进行分隔

总结:while,do while,for都是开发中常用的循环语句,for循环结构比较清晰,比较常用

4.2.4 嵌套循环

作用:在循环体中再嵌套一层循环,解决一些实际问题

例如我们想在屏幕打印如下图片,就需要利用嵌套循环

示例:

#include<iostream>
using namespace std;int main()
{//外层循环for (int i = 0; i < 10; i++){//内层循环for (int j = 0; j < 10; j++){cout << "* ";}cout << endl;//换行}system("pause");return 0;
}

4.3 跳转语句

4.3.1 break语句

作用:用于跳出选择结构或者循环结构

break使用的时机:

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

4.3.2 continue语句

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

continue和break的区别:

  • 执行continue时只会跳过当前循环后面的代码,直接执行下一次循环语句
  • 执行break时将直接跳出循环,不再继续执行循环语句

4.3.3 goto语句

作用:可以无条件跳转语句

语法: goto  标记;

解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置

goto again;//创建一个标记
again://标记
//遇到goto again;这条语句就会跳转到again:标记处

goto语句,也被很多人调侃为飞雷神语句,为什么要叫飞雷神语句?可以将 goto again; 看作水门,而again:就是飞雷神。again不是goto语法,而是标记名称,标记名称可以根据自己需求起名。

goto语句有害论(禁术goto):

但是我们一般是不推荐使用goto语句的,因为goto语句多了就不断地跳来跳去,反而会影响到代码的逻辑结构,不太方便别人去阅读我们的代码。我们只需要知道有goto语句这个知识点就行,以便看到别人的代码有goto语句知道这是什么意思,但是不推荐大家随意使用。

5. 数组

5.1 概述

所谓数组,就是一个集合,里面存放了相同类型的数据元素

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

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

5.2 一维数组

5.2.1 一维数组定义方式

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

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

示例:

//第一种
int arr[10];
//暂时不用数组,就先定义好一个明确大小的数组//第二种
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//开辟数组时明确大小并给这个数组初始化//第三种
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//没有明确大小系统会自动开辟一块10个元素的空间存储数组初始化的元素

5.2.2 一维数组数组名

一维数组名称的用途:

  1. 可以统计整个数组在内存中的长度
  2. 可以获取数组在内存中的首地址
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sz = sizeof(arr)/sizeof(arr[0]);//结果为10

sizeof是计算类型或变量所占内存空间的大小,以字节为单位,sizeof(arr)则是计算数组的整个大小,10个元素每个元素都是int 4个字节的大小,所以sizeof(arr)就是40个字节大小。然后再除以一个元素的大小得到的就是元素个数。

注:数组名是首元素的地址

5.3 二维数组

二维数组就是在一维数组上多加了一个维度

可以将二维数组看作存储多个一维数组,二维数组的每个元素都是一个一维数组。

5.3.1 二维数组定义方式

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

  1. 数组类型   数组名[  行数  ][  列数  ] ;
  2. 数组类型   数组名[  行数  ][  列数  ]  =  {  {数据1,数据2}  ,{数据3,数据4}  };
  3. 数组类型   数组名[  行数  ][  列数  ]  =  {  {数据1,数据2,数据3,数据4 };
  4. 数组类型   数组名[   ][  列数  ]  =  {  {数据1,数据2,数据3,数据4 };

建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性

注意:初始化二维数组时,行数可以省略,但是列数不能省略

5.3.2 二维数组数组名

  • 查看二维数组所占内存空间
  • 获取二维数组首地址

和一位数组数组名相同,sizeof(数组名)是数组整体所占内存空间大小,数组名本身就是首元素地址。

注:二维数组的每个元素都是一个元素个数为列数的一维数组

二维数组数组名==第一个元素一维数组的地址==第一个元素一维数组的首元素地址

6. 函数

6.1 概述

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

一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能

6.2 函数的定义

函数的定义一般主要有5个步骤:

1、返回值类型

2、函数名

3、参数列表

4、函数体语句

5、return表达式

语法:

返回值类型 函数名(参数列表)
{函数体语句return表达式
}
  • 返回值类型:一个函数可以返回一个值,在函数定义中
  • 函数名:给函数起个名称
  • 参数列表:使用该函数时,传入的数据
  • 函数体语句:花括号内的代码,函数内需要执行的语句
  • return表达式:和返回值类型挂钩,函数执行完后,返回相应的数据

6.3 函数的调用

创建好函数需要调用函数

函数名(参数);

上面就是调用函数的语法,如果有返回值前面可以创建一个整型变量来接收函数的返回值

注:函数调用时给函数传递的是实际参数,简称实参。而函数内部的参数列表并没有真实的参数,只是形式上的,所以简称形参。当函数为了接收函数调用传递过来的实参时就会创建空间来存储,这被称为形参的实例化

6.4 传值调用和传址调用

概念:调用函数传参时有两中形式,分别是是传数值或传地址

传值调用:将值直接传递给形参,对形参作出改变不会影响到实参。

传址调用:将地址传递给形参,通过地址可以对实参做出改变。

6.5 函数的常见样式

常见的函数样式有4种

  1. 无参无返
  2. 有参无返
  3. 无参有返
  4. 有参有返

6.6 函数的声明

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

语法:

返回类型 函数名(参数列表);

与函数定义很像,只不过函数定义有函数体,而函数声明没有函数体所以函数声明后面要加上一个分号。

  •  函数的声明可以多次,但是函数的定义只能有一次

6.7 函数的分文件编写

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

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

  1. 创建后缀名为.h的头文件
  2. 创建后缀名为.cpp的源文件
  3. 在头文件中写函数的声明
  4. 在源文件中写函数的定义

swap.h头文件

//swap.h文件
#include<iostream>
using namespace std;//实现两个数字交换的函数声明
void Swap(int* x,int* y);

swap.cpp源文件

//swap.cpp文件
//包含自定义头文件,需要证明这个文件是与swap.h文件关联的
#include "swap.h" //函数定义
void Swap(int* x,int* y)
{int a = *x;*x = *y;*y = a;
}

总结:swap.cpp也需要包含头文件说明这两个文件的函数声明和定义是关联的,其他文件想要调用swap.cpp函数,只需要包含头文件swap.h就行,因为swap.h和swap.c是关联的。

7. 指针

7.1 指针的基本概念

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

  • 内存编号是从0开始记录的,一般用十六进制表示
  • 可以利用指针变量保存地址

7.2 指针的定义和使用

指针变量定义语法: 类型 * 变量名 

示例:

#include<iostream>
using namespace std;int main()
{int a = 10;int* pa = &a;cout << "a = " << a << endl;cout << "pa = " << *pa << endl;*pa = 20;cout << "a = " << a << endl;system("pause");return 0;
}

运行代码:

7.3 指针所占内存

提问:指针变量也是需要开辟空间存储地址的,那这个空间也就是指针(地址)到底有多大呢?

答案是:4/8个字节,指针的大小是由编译器决定的,因为CPU是通过地址总线来传输地址信号,在32位操作系统下地址总线是32根,指针(地址)的大小是4个字节。在64位操作系统下地址总线是64根,指针(地址)的大小是8个字节。

7.4 空指针和野指针

空指针:指针变量指向内存中编号为0的空间,只要给指针变量赋值空指针NULL我们就不可以解引用,因为0~255之间的编号内存空间是系统占用的

用途:初始化指针变量

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

//NULL==0==空指针
int* p = NULL;

如果初始化指针变量不给地址就赋值一个空指针NULL,就是为了防止我们使用到野指针。

野指针:就是指向了为分配的内存空间,就是野指针,对未分配的内存空间解引用会报错。

7.5 const修饰指针

const修饰指针有三种情况:

  1. const修饰指针  ---常量指针
  2. const修饰常量  ---指针常量
  3. const即修饰指针,又修饰常量

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

int a = 10;
const int *pa = NULL;
pa = &a;//正确
*pa = 20;//错误

因为这里修饰的就是*pa是常量,所以*pa不能修改所指向的内存空间。

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

int a = 10;
int b = 20;
int *const pa = &a;
*pa = 20;//正确
pa = &b;//错误

 const修饰pa本身就是pa不可以再指向其他地址。

3. const即修饰指针,又修饰常量

int a = 10;
int b = 20;
cosnt int* const pa = &a;
*pa = 20;//错误
pa = &b;//错误

 既不想让*pa修改所指向的内存空间,又不想让pa指向其他空间就可以让两边都修饰const

8. 结构体

8.1 结构体基本概念

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

8.2 结构体定义和使用

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

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

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

示例:

//第三种创建变量方式
struct stu
{int a;int b;char c;
}s3;//第一种方式
struct stu s1;
//第二种方式
struct stu s2 = {10,20,'a'};

其实在第一种和第二种的方式创建变量时,是可以把前面的struct给省略掉的,例如:

//第三种创建变量方式
struct stu
{int a;int b;char c;
}s3;//第一种方式
stu s1;
//第二种方式
stu s2 = {10,20,'a'};

第三种不可以。 

结构体的使用:

//结构体访问成员
变量名.成员//结构体指针访问成员
变量名->成员

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

总结2:创建结构体变量时,关键字struct可以省略

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

8.3 结构体数组

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

语法: struct  结构体名  数组名[元素个数] = {  {}  ,  {}  ,  . . .  {}} 

示例:

#include<iostream>
using namespace std;struct student
{char name[12];int age;int score;
};
int main()
{int n = 3;struct student* stu = (struct student*)malloc(sizeof(struct student) * n);for (int i = 0; i < n; i++){cin >> stu[i].name >> stu[i].age >> stu[i].score;}for (int i = 0; i < n; i++){cout << "名字:" << stu[i].name << " 年龄:" << stu[i].age << " 分数:" << stu[i].score << endl;}system("pause");return 0;
}

代码输出:

8.4 结构体指针

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

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

8.5 结构体嵌套结构体

在结构体中可以定义另一个结构体作为成员,用于解决实际问题。

例如:需要一个结构体来存储学生信息,然后再需要一个结构体存储教师信息,教师信息需要嵌套存储学生的结构体来表示这是自己的学生。

示例:

//定义一个存储学生信息的结构体
struct student
{//名字char name[12];//年龄int age;//性别char ginder[5];
};
//定义一个存储教师信息的结构体
struct teacher
{//名字char name[12];//年龄int age;//教职编号int id;//管理学生struct student stu[50];//结构体嵌套
}

8.6 结构体做函数参数

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

传递方式有两种:

  • 值传递
  • 地址传递

还是老样子,如果需要改变结构体里的成员就传递地址,如果不需要改变成员就传值。

例如:将结构体传给函数打印函数的成员就传值。将结构体传给函数并修改结构体内的成员就传址

9. string功能解析

知识点重点:string字符串类型追加和两个string字符串判断

#include<iostream>
using namespace std;int main()
{string str1 = "hello ";string str2 = "world";//C++中的字符串类型变量是可以用下面这种方式追加字符串和字符的str1 += str2;cout << "str1 = " << str1 << endl;system("pause");return 0;
}

总结:只有string类型的变量可以直接以+=的方式追加字符或字符串

string字符串类型和char[ ]字符数组的区别:

1. 定义容量:

string:string类会自己增加容量,是动态,所以我们一开始创建是不需要专门指定大小

char[ ]:char[ ]一开始需要在[ ]内部指定大小

2. 字符串追加:

string:string追加字符串或字符不用任何库函数,只需要string类型变量+=(字符或字符串)

char[ ]:char[ ]字符数组不同,它需要strcat函数将一个字符数组的字符串追加到另一个字符串的后面

3. 字符串比较:

string:string也是可以不用自己调用库函数直接和其他字符串进行比较,直接判断string字符串==其他字符串

char[ ]:char[ ]是需要调用库函数strcmp来和其他字符串进行比较

总结:因为string是类,封装了这功能,所以我们是不需要自己调用库函数的,因为string里封装了这些功能。

相关文章:

初阶C++笔记第一篇:C++基础语法

虽然以下大多数知识点都在C语言中学过&#xff0c;但还是有一些知识点和C语言不同&#xff0c;比如&#xff1a;代码格式、头文件、关键字、输入输出、字符串类型等... 1. 初识C 1.1 第一个C程序 编写C分为4个步骤&#xff1a; 创建项目创建文件编写代码运行程序 C的第一条…...

java基础 流(Stream)

Stream Stream 的核心概念核心特点 Stream 的操作分类中间操作&#xff08;Intermediate Operations&#xff09;终止操作&#xff08;Terminal Operations&#xff09; Stream 的流分类顺序流&#xff08;Sequential Stream&#xff09;并行流&#xff08;Parallel Stream&…...

【AI】prompt engineering

prompt engineering ## prompt engineering ## prompt engineering ## prompt engineering 一、定义 Prompt 工程&#xff08;Prompt Engineering&#xff09;是指在使用语言模型&#xff08;如 ChatGPT、文心一言等&#xff09;等人工智能工具时&#xff0c;设计和优化输入提…...

无需libpacp库,BPF指令高效捕获指定数据包

【环境】无libpacp库的Linux服务器 【要求】高效率读取数据包&#xff0c;并过滤指定端口和ip 目前遇到两个问题 一是手写BPF&#xff0c;难以兼容&#xff0c;有些无法正常过滤二是性能消耗问题&#xff0c;尽可能控制到1% 大方向&#xff1a;过滤数据包要在内核层处理&…...

LeetCode算法题(Go语言实现)_36

题目 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节点…...

react实现上传图片到阿里云OSS以及问题解决(保姆级)

一、优势 提高上传速度&#xff1a;前端直传利用了浏览器与 OSS 之间的直接连接&#xff0c;能够充分利用用户的网络带宽。相比之下&#xff0c;后端传递文件时&#xff0c;文件需要经过后端服务器的中转&#xff0c;可能会受到后端服务器网络环境和处理能力的限制&#xff0c;…...

无法看到新安装的 JDK 17

在 Linux 系统中使用 update-alternatives --config java 无法看到新安装的 JDK 17&#xff0c;可能是由于 JDK 未正确注册到系统备选列表中。 一、原因分析 JDK 未注册到 update-alternatives update-alternatives 工具需要手动注册 JDK 路径后才能识别新版本。如果仅安装 JDK…...

LeetCode 3396.使数组元素互不相同所需的最少操作次数:O(n)一次倒序遍历

【LetMeFly】3396.使数组元素互不相同所需的最少操作次数&#xff1a;O(n)一次倒序遍历 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-number-of-operations-to-make-elements-in-array-distinct/ 给你一个整数数组 nums&#xff0c;你需要确保数组中的元素…...

Vue2 快速过度 Vue3 教程 (后端学习)

隔好长一段时间没有写文章了&#xff0c;因为最近公司一个项目进度很赶&#xff0c;导致一直加班&#xff0c;没有时间空出来学习新的东西&#xff0c;这次趁着周末&#xff0c;赶紧补一下之前落下的一直想重新学一下整个大前端生态的想法&#xff0c;这次写一篇自己学习Vue3的…...

供应链管理-职业规划:数字化供应链管理专家 / 供应链管理商业模式专家 / 供应链管理方案专家

一、背景阐述 依据联合国产业分类标准&#xff0c;工业体系被细致划分为41个工业大类、207个工业中类以及666个工业小类。中国凭借其独特的产业布局&#xff0c;成为全球唯一一个全面涵盖所有这些门类的国家&#xff0c;成功构建起独立且完备的现代工业体系。这一辉煌成就&…...

无状态版的DHCPv6是不是SLAAC? 笔记250405

无状态版的DHCPv6是不是SLAAC? 笔记250405 无状态版 DHCPv6 不是 SLAAC&#xff0c;但二者在 IPv6 网络中可协同工作。以下是核心区别与协作关系&#xff1a; 本质区别 特性SLAAC无状态 DHCPv6主要功能生成 IPv6 地址&#xff08;基于路由器通告的前缀&#xff09;分发 DNS、…...

遍历算法及其应用详解

李升伟 整理 什么是遍历&#xff1f; 遍历是指按照某种规则或顺序&#xff0c;系统地访问数据结构&#xff08;如树、图等&#xff09;中的每个节点一次且仅一次的过程。遍历是算法设计中的基本操作&#xff0c;用于访问、检查或修改数据结构中的所有元素。 主要遍历算法 1…...

Python 字典和集合(常见的映射方法)

本章内容的大纲如下&#xff1a; 常见的字典方法 如何处理查找不到的键 标准库中 dict 类型的变种set 和 frozenset 类型 散列表的工作原理 散列表带来的潜在影响&#xff08;什么样的数据类型可作为键、不可预知的 顺序&#xff0c;等等&#xff09; 常见的映射方法 映射类型…...

基于大模型的ALS预测与手术优化系统技术方案

目录 技术方案文档:基于大模型的ALS预测与手术优化系统1. 数据预处理与特征工程模块流程图伪代码2. 多模态融合预测模型模型架构图伪代码3. 术中实时监测与动态干预系统系统流程图伪代码4. 统计验证与可解释性模块验证流程图伪代码示例(SHAP分析)5. 健康教育与交互系统系统架…...

创建一个简单的HTML游戏站

创建一个简单的HTML游戏站涉及多个步骤&#xff0c;包括规划网站结构、设计用户界面、编写游戏逻辑以及测试和部署。下面是一个详细的步骤指南&#xff1a; 1. 规划网站结构 确定目标受众&#xff1a;了解你的目标用户群体。选择游戏类型&#xff1a;决定你要开发的游戏类型&…...

Matlab轴承故障信号仿真与故障分析

1.摘要 本文介绍了一个基于Matlab的轴承故障信号仿真与分析程序&#xff0c;旨在模拟和分析轴承内圈故障信号的特征。程序首先通过生成故障信号、共振信号和调制信号&#xff0c;添加噪声和离散化处理&#xff0c;构建模拟的振动信号&#xff0c;并保存相关数据。通过快速傅里…...

Linux 进程 | 概念 / 特征 / 状态 / 优先级 / 空间

注&#xff1a; 本文为 “Linux 进程” 相关文章合辑。 未整理去重。 Linux 进程概念&#xff08;精讲&#xff09; A little strawberry 于 2021-10-15 10:23:55 发布 基本概念 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等。 内核观点&#xff…...

项目中如何防止超卖

什么是超卖&#xff1f;假如只剩下一个库存&#xff0c;却被多个订单买到了&#xff0c;简单理解就是库存不够了还能正常下单。 方案1&#xff1a;数据库行级锁 1. 实体类 Data TableName("product") public class Product {TableId(type IdType.AUTO)private Lon…...

重回全面发展亲自操刀

项目场景&#xff1a; 今年工作变动&#xff0c;优化后在一家做国有项目的私人公司安顿下来了。公司环境不如以前&#xff0c;但是好在瑞欣依然可以每天方便的买到。人文氛围挺好&#xff0c;就是工时感觉有点紧&#xff0c;可能长期从事产品迭代开发&#xff0c;一下子转变做项…...

3D珠宝渲染用什么软件比较好?渲染100邀请码1a12

印度珠宝商 Mohar Fine Jewels 和英国宝石商 Gemfields 在今年推出了合作珠宝系列——「Emeralds in Full Bloom」&#xff0c;它的灵感源自花草绽放的春季田野&#xff0c;共有 39 件作品&#xff0c;下面这个以植物为主题的开口手镯就是其中一件。 在数字时代&#xff0c;像这…...

【数据结构】邻接矩阵完全指南:原理、实现与稠密图优化技巧​

邻接矩阵 导读一、图的存储结构1.1 分类 二、邻接矩阵法2.1 邻接矩阵2.2 邻接矩阵存储网 三、邻接矩阵的存储结构四、算法评价4.1 时间复杂度4.2 空间复杂度 五、邻接矩阵的特点5.1 特点1解析5.2 特点2解析5.3 特点3解析5.4 特点4解析5.5 特点5解析5.6 特点6解析 结语 导读 大…...

【嵌入式-stm32电位器控制以及旋转编码器控制LED亮暗】

嵌入式-stm32电位器控制LED亮暗 任务1代码1Key.cKey.hTimer.cTimer.hPWM.cPWM.hmain.c 实验现象1任务2代码2Key.cKey.hmain.c 实验现象2问题与解决总结 源码框架取自江协科技&#xff0c;在此基础上做扩展开发。 任务1 本文主要介绍利用stm32f103C8T6实现电位器控制PWM的占空比…...

ragflow开启https访问:添加证书后,使用浏览器还是有警告,如何解决?

如果在 Windows 系统中安装了 PEM 证书(使用方法一通过证书管理器 MMC 导入),但浏览器仍然提示安全警告,可能有以下几个原因及解决方法: 1. 证书未正确安装到受信任的存储位置 问题:如果证书被导入到错误的存储位置(如“个人”而非“受信任的根证书颁发机构”),浏览器…...

字符串——面试考察高频算法题

目录 转换成小写字母 字符串转化为整数 反转相关的问题 反转字符串 k个一组反转 仅仅反转字母 反转字符串里的单词 验证回文串 判断是否互为字符重排 最长公共前缀 字符串压缩问题 转换成小写字母 给你一个字符串 s &#xff0c;将该字符串中的大写字母转换成相同的…...

Uniapp 集成极光推送(JPush)完整指南

文章目录 前言一、准备工作1. 注册极光开发者账号2. 创建应用3. Uniapp项目准备 二、集成极光推送插件方法一&#xff1a;使用UniPush&#xff08;推荐&#xff09;方法二&#xff1a;手动集成极光推送SDK 三、配置原生平台参数四、核心功能实现1. 获取RegistrationID2. 设置别…...

Plusar集群搭建-Ubuntu20.04-Winterm

1 背景 已经部署了Pulsar集群在生产上&#xff0c;新项目需要用到Pulsar。对Pulsar不熟&#xff0c;故搭建练手。 环境&#xff1a;Windows10vmwareUbuntu20.04&#xff0c;ssh工具使用的Winterm。 使用的是root账户&#xff0c;ubuntu防火墙都ufw disable了。 2 参考文档 集…...

selenium元素获取

from selenium import webdriver from selenium.webdriver.common.by import Bydriver webdriver.Chrome()driver.maximize_window()#最大化窗口 #隐式等待 driver.implicitly_wait(10)#打开网页 driver.get("https://www.zhipin.com/beijing/?kacity-sites-101010100&q…...

AI比人脑更强,因为被植入思维模型【50】邓克效应思维模型

giszz的理解&#xff1a;DK Effect&#xff0c;就是井底之蛙。这里有个启发&#xff0c;就是人的认知提升&#xff0c;有4个阶段&#xff0c;愚昧区、崩溃区、成长区、智慧区。也分别对应4个境界&#xff1a;自然境界、功利境界、道德境界、天地境界。我个人觉得自己刚刚过了崩…...

8、nRF52xx蓝牙学习(boards.h文件学习)

boards.h文件的代码如下&#xff1a; #ifndef BOARDS_H #define BOARDS_H#include "nrf_gpio.h" #include "nordic_common.h"#if defined(BOARD_NRF6310)#include "nrf6310.h" #elif defined(BOARD_PCA10000)#include "pca10000.h" #…...

声明文件.d.ts

在 TypeScript 中&#xff0c;.d.ts 文件是类型声明文件&#xff08;Declaration Files&#xff09;&#xff0c;用于描述 JavaScript 库或模块的类型信息&#xff0c;但不包含具体实现。它们帮助 TypeScript 编译器进行类型检查&#xff0c;同时保持与纯 JavaScript 的兼容性。…...