0614
C++工程师
- 第0章 视频课的链接
- 第1章 C++岗位知识图谱
- 第2章 C++八股文
- 第3章 算法题视频课
- 第4章 项目制作与技能提升
- 第5章 高频考点与真题精讲
-
- 5.1 指针
- 5.2 函数
-
- 5.2.1 分文件编写
- 5.2.2 防止头文件重复包含
- 补充:多文件编译
- 5.2.3 指针变量作为函数的参数
- 5.2.4 指针作为函数返回值类型
- 5.2.5 函数内修改外部指针的指向
- 5.2.6 函数和数组
- 5.2.7 函数和字符串
- 5.2.8 函数和结构体
- 5.2.9 主函数传参 int main(int argc, char * argv[]);
- 5.2.10 递归
- 5.2.11 函数指针
- 5.2.12 宏常量 & 宏函数 #define
- 5.2.13 内联函数inline
- 5.2.14 引用
- 5.2.15 引用作为函数参数
- 5.2.16 常量引用 const int&
- 5.2.17 引用和结构体(☆☆☆函数传参的时候 引用传递?地址传递?值传递?)
- 5.2.18 引用作为函数返回值
- 5.2.19 默认参数(从右往左的顺序设置默认值)
- 5.2.20 函数重载(Overload)-->静态多态
- 5.2.21 函数重载的注意事项
- 5.2.22 extern "C" 按照C语言的方式去编译
- 5.2.23 字符和字符串处理函数
- 5.3 面向对象
第0章 视频课的链接
点这里,这个视频课中只看了第四章和第五章,第五章主要讲的是C++的知识,第四章主要讲的项目相关的知识,本篇笔记是第五章的内容。
第1章 C++岗位知识图谱
第2章 C++八股文
E:\找工作\C++八股文\C面试宝典完整版最最最新.pdf
第3章 算法题视频课
第4章 项目制作与技能提升
笔记链接:Linux高并发服务器开发—笔记1
第5章 高频考点与真题精讲
视频配套资料:E:\读研\C++\牛客网—2021C++秋招集训营
主要内容:
这里面好像也包括了上面的项目的复习,接下来就把第5章的视频笔记记录下来。
5.1 指针
1.地址所占的内存空间大小
32位系统上占4个字节;64位系统上占8个字节。
int* p = nullptr;
cout << "地址所占内存大小:" << sizeof(p) << endl;
编译运行结果:
地址所占内存大小:8
2.声明和初始化指针变量
3.野指针和空指针
野指针就是把任意数值赋给指针变量,这没有任何意义,因为野指针指向的区域是未知的。
4.指针的宽度和跨度(a和&a的区别)
①指针变量的自身类型:
②指针变量的指向类型:
③指针变量所取内容的宽度:
由指针变量所指向的类型长度决定。
int num = 0x51525354;
int* p = #
cout << "*p = " << hex << *p << endl;
short *p1 = (short*)#
cout << "*p1 = " << hex << *p1 << endl;
编译运行的结果:
*p = 51525354
*p1 = 5354
指针变量p
指向的类型是int
类型,int的长度是四个字节;
指针变量p1
指向的类型是short
类型,short的长度是两个字节。
☆☆☆④指针变量+1
的跨度:
由指针变量所指向的类型的大小决定。
示例1:
short* s1 = nullptr;
cout << "s1 = " << s1 << endl;
cout << "s1 + 1 = " << s1 + 1 << endl;
int* p1 = nullptr;
cout << "p1 = " << p1 << endl;
cout << "p1 + 1 = " << p1 + 1 << endl;
编译运行的结果:
s1 = 0
s1 + 1 = 0x2
p1 = 0
p1 + 1 = 0x4
指针变量s1
指向的类型是int
类型,int的大小是四个字节;
指针变量p1
指向的类型是short
类型,short的大小是两个字节。
示例2:
int arr2[10];
cout << "arr2 = " << arr2 << endl; //arr2 = 0x7fffffffdfe0
cout << "arr2 + 1 = " << arr2 + 1 << endl; //arr2 + 1 = 0x7fffffffdfe4
cout << "&arr2 = " << &arr2 << endl; //&arr2 = 0x7fffffffdfe0 dfe0 + 0028(十进制的40) = e008
cout << "&arr2 + 1 = " << &arr2 + 1 << endl; //&arr2 + 1 = 0x7fffffffe008
arr2
是数组首元素的地址,类型是int *
或者int arr2[]
;
arr2
+ 1每次加1个int的大小,即4个字节。
&arr2
是整个数组的地址,也叫数组指针,类型是int (*)[10]
;
&arr2
+ 1每次加整个数组的大小,即40个字节。
(注:arr2
和&arr2
都是地址,前者指向一个数组元素的地址,后者指向整个数组的地址,所以它们的跨度不一样;
其中&arr2
可以看下面的7.数组指针和指针数组)
示例3:(这个示例好)
#include<stdlib.h>
#include<stdio.h>
int main(int argc, char* argv[]){
int a[4] = {
1, 2, 3, 4};
//int* p = (int*)(&a + 1); //结果是4
int* p = (int*)(a + 1); //结果是1
printf("%d\n", *(p - 1));
return 0;
}
5.const和指针 —(指针常量和常量指针)
指针常量和常量指针,见C++笔记4:C++中const和指针。
指针常量(常指针):指针是个常量,指向固定;int* const p;
常量指针:指向常量的指针,指向的值固定;const int* p;
示例:
#include<iostream>
using namespace std;
int main(){
int num1 = 10;
int num2 = 20;
int num3 = 30;
//常量指针:指向常量的指针
int const *p1;
p1 = &num1;//指针p1(我)指向num1(你) ---指向的值固定,即(*p1)不能改变,但p1可以改变
//(*p1)++;//不能通过p1来修改num1的值(不能通过我来修改你)
cout << "p1 = " << p1 << "; &num1 = " << &num1 << "; num1 = " << num1 << endl;//p1 = 0x7fffffffe038; &num1 = 0x7fffffffe038; num1 = 10
++num1; //可以通过num1来修改自己的值(可以通过你来修改你自己)
cout << "p1 = " << p1 << "; &num1 = " << &num1 << "; num1 = " << num1 << endl;//p1 = 0x7fffffffe038; &num1 = 0x7fffffffe038; num1 = 11
p1 = &num2;//可以修改p1指向的内容(可以修改我自己指向的内容)
cout << "p1 = " << p1 << "; &num1 = " << &num1 << "; num1 = " << num1 << endl;//p1 = 0x7fffffffe03c; &num1 = 0x7fffffffe038; num1 = 11(p1改变)
//指针常量:指针是个常量,所以必须要初始化 ---指向固定,即p2不能改变,但(*p2)可以改变
//int * const p2;//没初始化为报错
int * const p2 = &num2;//指针p2(我)指向num2*(你)
cout << "p2 = " << p2 << "; &num2 = " << &num2 << "; num2 = " << num2 << endl;//p2 = 0x7fffffffe03c; &num2 = 0x7fffffffe03c; num2 = 20
(*p2)++;//可以通过p2来修改num2的值(可以通过我来修改你的值)
cout << "p2 = " << p2 << "; &num2 = " << &num2 << "; num2 = " << num2 << endl;//p2 = 0x7fffffffe03c; &num2 = 0x7fffffffe03c; num2 = 21((*p2)改变)
++num2; //也可以通过num2来修改自己的值(可以通过你来修改你自己)
cout << "p2 = " << p2 << "; &num2 = " << &num2 << "; num2 = " << num2 << endl;//p2 = 0x7fffffffe03c; &num2 = 0x7fffffffe03c; num2 = 22
//p2 = &num3;//不能修改p2指向的内容(不可以修改我自己指向的内容)
//静态常量指针和普通的常量指针
static const char*p3;
char const *p4;
cout << "p3 = " << p3 << endl;//ok,因为静态变量会默认赋初值
//cout << "p4 = " << p4 << endl;//编译不过,因为p4的初始值不确定
return 0;
}
题目:(静态变量和普通变量 & 常量指针)
6.指针在数组中的操作(☆☆☆ * 和 前缀++ 和 后缀++ )
参考链接:*与++优先级:
- 前缀递增递减和
*
优先级相同,从右到左; - 后缀递增递减比前缀优先级高,从左到右。
*和后缀++:
*p++
相当于*(p++)
:先输出*p
,然后p
自加一;
(*p)++
:输出*p
,然后(*p
)自加一;
*和前缀++:
*++p
相当于*(++p)
:先让p
自加一,然后再取*p
;
*(++p)
:先让p
自加一,然后再取*p
;
++*p
相当于 ++(*p)
:先输出*p
,然后(*p
)自加一;
++(*p)
:先输出*p
,然后(*p
)自加一;
示例1:
#include<iostream>
using namespace std;
int main(){
// 案例:
//前缀递增递减和*优先级相同,从右到左;
//后缀递增递减比前缀优先级高,从左到右;
int arr1[5] = {
10,20,30,40,50 };
int* p2 = arr1;
cout << *p2++ << endl; //10 p2指向arr1[1]
cout << (*p2)++ << endl; //20 p2指向arr1[1], arr[1]变成21
cout << *p2 << endl; //21
cout << *++p2 << endl; //30 p2指向arr1[2]
cout << *(++p2) << endl; //40 p2指向arr1[3]
cout << ++*p2 << endl; //40 p2指向arr1[3],arr1[3]变成41
cout << *p2 << endl; //41
cout << ++(*p2) << endl; //41 p2指向arr1[3],arr1[3]变成42
cout << *p2 << endl; //42
for(int& x : arr1) cout << x << "; ";//10; 21; 30; 42; 50;
cout << endl;
return 0;
}
示例2:
int* p = arr;
p[i]
等价于*(p + i)
,等价于*(arr + i)
,等价于arr[i]
;
int* p1 = &arr[2];
p1[1]等价于*(p1 + 1)
,即arr[3]
;
p1[-1]等价于*(p1 - 1)
,即arr[1]
// 创建一个数组
int arr[5] = {
10,20,30,40,50 };
int* p = arr; //等价于 int* p; p = arr;
//int (*p)[5] = &arr;//数组指针
//int *p[5];//指针数组
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
cout << p[i] << endl;//p[i]等价于*(p + i),等价于*(arr + i) ,等价于arr[i]
}
cout << sizeof(arr) << endl; // 20=4*5
cout << sizeof(p) << endl; // 8个字节,64位系统
// 不要认为p只能保存首元素的地址
int* p1 = &arr[2];
cout << "p1[1] = " << p1[1] << endl;//p1[1]等价于*(p1 + 1),即arr[3]
cout << "p1[-1] = " << p1[-1] << endl;//p1[-1]等价于*(p1 - 1),即arr[1]
7.数组指针和指针数组
数组指针:指向数组的指针
int arr[5] = {
10,20,30,40,50 };
int (*p)[5] = &arr;//数组指针
指针数组:元素为指针(地址)的数组
int num1 = 10;
int num2 = 20;
int num3 = 30;
int num4 = 40;
int * arr[4] = {
&num1, &num2, &num3, &num4};
示例1:(数组指针)
int arr[10];
int (*p)[5] = &arr;//错误,"int (*)[10]" 类型的值不能用于初始化 "int (*)[5]" 类型的实体
int (*p)[10] = &arr;//ok
int (*p)[10] = arr;//错误,"int *" 类型的值不能用于初始化 "int (*)[10]" 类型的实体
cout << arr << endl;//arr的类型:int * 或者 int arr[]
cout << &arr << endl;//&arr的类型为:int (*)[10]
arr
的类型:int *
或者 int arr[]
;
&arr
的类型为:int (*)[10]
,也叫数组指针;
注:arr
和&arr
都是地址,前者指向一个数组元素的地址,后者指向整个数组的地址,所以它们的跨度不一样;
示例2:(指针数组)
char name1[10];
char name2[10];
char name3[10];
char *pp[3] = {
name1, name2, name3};//ok
char *pp[3] = {
&name1, &name2, &name3};//错误,
//"char (*)[10]" 类型的值不能用于初始化 "char *" 类型的实体
name1
的类型:char *
或者 char name1[10]
;
&name1
的类型为:char (*)[10]
,也叫数组指针;
而指针数组中存放的是指针变量,即int *
或者char *
,所以上面示例中的最后一行是错误的。
示例3:(数组指针)
char aaa[][3] = {
'a', 'b', 'c', 'd', 'e', 'f'};
char (*p)[3] = aaa;
cout << "" << **p << endl;//'a'
cout << "" << *(*(p + 1) + 2) << endl;//'f'
p++;
cout << "" << **p << endl;//'d'
8.二级指针(加引用和解引用的规则)
int num = 10;
int * p = #
int ** q = &p;
*p : 获取的是 num 的值
*q : 获取的是 num 的地址值
**q : 获取的是 num 的值
加引用的规则:
num
是int
类型,给num
前面加一个&
,就要给int
后面加个*
,那么&num
就是int*
类型;
p
是int*
类型,给p
前面加一个&
,就要给int*
后面加个*
,那么&p
就是int**
类型。
解引用的规则:
q
是int**
类型,给q
前面加一个*
,int**
就要减个*
,那么*q
就是int*
类型;
p
是int*
类型,给p
前面加一个*
,int*
就要减个*
,那么*p
就是int
类型。
9.☆☆☆字符数组 char指针 字符串常量
这部分内容之前在
C++ Primer Plus(嵌入式公开课)—第4章 复合类型中的第四章4.2 字符串(C语言)
和
我的C++八股文中的笔记5
中有提到,这里做一个完整的总结。
示例1:arr是数组首元素的地址
int arr[3] = {
1,2,3 };
int* p = arr;
cout << p << endl; // 0x7fffffffdffc 输出的是地址值。
cout << *p << endl;//1 输出的是元素值
示例2:flower 也是字符数组的首元素地址
#include <iostream>
#include<string.h> // strlen函数的头文件
using namespace std;
int num = 20;//全局变量
int main() {
//1.字符数组(C风格的字符串)
char flower[10] = "rose";//等价于 char flower[10] = {'r', 'o', 's', 'e', '\0'};
cout << flower << endl;//rose
cout << "sizeof(flower) = " << sizeof(flower) << endl;//10 字符数组的大小
cout << "strlen(flower) = " << strlen(flower) << endl;//4 字符串的大小
cout << "字符数组的地址:" << &a