C++基础从0到1入门编程(一)

news2024/11/28 14:33:49

系统学习C++
方便自己日后复习,错误的地方希望积极指正
参考视频:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

1 第一个C程序-HelloWorld

编写一个C++程序分为四个步骤:
(1)创建项目
(2)创建文件
(3)编写代码
(4)运行程序

#include <iostream>
using namespace std;
/*
main 是一个程序的入口
每个程序有且只有一个
*/
int main()
{
    cout << "hello world" << endl; // 输出Hello world
    system("pause");
    return 0;
}

2 程序的注释

编译器不会执行注释的内容

作用:代码添加说明,方便阅读
两种格式:
(1)单行注释://
通常放在语句的上方,或者一条语句的结尾
(2)多行注释:/**/
通常放在一段代码的上方

3 变量

变量存在的意义:方便我们管理内存空间
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
在这里插入图片描述

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

4 常量

作用:用于记录程序中不可更改的数据
定义常量的方式:
(1)#define 宏常量:#define 常量名 常量值
通常在文件上方定义,表示一个常量
(2)const 修饰变量:const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const,修改变量为常量,不可修改

#include <iostream>
using namespace std;
#define Day 7

int main()
{
	cout << Day << endl;
	const int month = 12;
	system("pause");
	return 0;
}

5 C++常用编程关键字

作用:C++预先保留的单词(标识符)

在定义变量或者常量时,不要用关键字,否则产生歧义

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    int a = 10;
    // int int = 10; 错误,第二个int是关键字
    system("pause");
    return 0;
}

6 标识符命名规则

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

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

给变量起名的时候,最好能够做到见名知意

7 数据类型

7.1 整型

C++规定在创建一个变量或者常量时,必须指定相应的数据类型,否则无法给变量分配内存。
数据类型存在意义:给变量分配合适的内存空间
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    short num1 = 10; // (-32768- 32767)
    int num2 = 10;
    long num3 = 10;
    long long num4 = 10;
    
    cout << "num1 = " << sizeof(num1) << endl; // 2
    cout << "num2 = " << sizeof(num2) << endl; // 4
    cout << "num3 = " << sizeof(num3) << endl; // 4
    cout << "num4 = " << sizeof(num4) << endl; // 8
    
    system("pause");
    return 0;
}
7.1.1 整数的书写

整数默认是十进制,一个表示十进制的数字不需要任何特殊的格式
(1)二进制
二进制由 0 和 1 两个数字组成,书写必须以0b或0B开头
(2)八进制
(3)十六进制
Tip:在C++中,不要在十进制数前面加0,会被编译器当成八进制,还有,不要随便删掉别人程序中整数前面的0,它不是多余的

#include <iostream>
using namespace std;

int main()
{
    // 十进制
    int a = 100;
    cout << a << endl; // 100
    // 二进制
    int b = 0b101; // 5
    int c = 0B1;   // 1
    cout << b << " " << c << endl;
    // 八进制(设备的权限)
    int d = 015;   // 13
    int e = -0101; // -65
    cout << d << " " << e << endl;
    // 十六进制(内存的地址)0 ~ 9 A ~ F a ~ f
    int m = 0X2A; // 42
    int n = -0XA0; // -160
    cout << m << " " << n << endl;
    return 0;
}
7.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型 或者 变量)

#include <iostream>
using namespace std;
// short < int <= long <= longlong
int main()
{
    short num1 = 10;
    cout << sizeof(num1) << ' ' << sizeof(short);
    system("pause");
    return 0;
}
7.3 实型(浮点型)

作用:用于表示小数
(1)单精度 float
(2)双精度 double
区别:表示的有效数字范围不同
在这里插入图片描述

#include <iostream>
using namespace std;
// 默认情况下,输出一个小数,会显示6位有效数字
int main()
{
    float f1 = 3.1415926f; // 默认double,在后面加f 让double - > float 3.14159
    cout << f1 << endl;
    double d1 = 3.1415926;
    cout << d1 << endl;
    // float double占用的内存空间
    cout << sizeof(float) << ' ' << sizeof(double) << endl;// float:4 double:8
    // 科学计数法
    float f2 = 3e2; // 3 * 10^2 = 300
    cout << f2 << endl;
    float f3 = 3e-2; // 3 * 0.1^2 = 0.03
    cout << f3 << endl;
    system("pause");
    return 0;
}
7.4 字符型

作用:字符型变量用于显示单个字符
语法:char ch = 'a';

Tip:
(1) 在显示字符型变量,用单引号,不能用双引号
(2) 单引号内只能有一个字符,不能是字符串

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

#include <iostream>
using namespace std;

int main()
{
    // 字符型变量创建
    char ch = 'A';
    cout << ch << endl;
    // 字符型变量所占内存
    cout << sizeof(char) << endl;
    // 字符型变量常见错误
    /* char ch2 = "s";
     * char ch2 = 'ads';
     */
    // 字符型变量对应的ASCII编码 a-97 A-65
    cout << (int)ch << endl;
    system("pause");
    return 0;
}

在这里插入图片描述

7.5 转义字符

作用:用于表示一些不能显示出来的ASCII字符
现阶段常用的转义字符:\n \\ \t

#include <iostream>
using namespace std;

int main()
{
    // 换行符
    cout << "hello world" << '\n';
    // 反斜杠
    cout << "\\" << endl;
    // 水平制表符 整齐输出数据
    cout << "aaa\twad" << endl; // aaa(5个空格)wad 8个
    cout << "aaaaa\twad" << endl;
    cout << "aaaa\twad" << endl;
    system("pause");
    return 0;
}
7.6 字符串型

作用:用于表示一串字符
两种风格:

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

C++风格字符串,需要包含头文件 <string>

#include <iostream>
#include <string>
using namespace std;

int main()
{
    cout << "hello world" << endl;
    // char 字符串名[]
    // =后面用双引号包含起来字符串
    // C风格字符串
    char str1[] = "hello world";
    cout << str1 << endl;
    // C++风格字符串,需要包含头文件<string>
    string str2 = "hello world";
    cout << str2 << endl;
    system("pause");
    return 0;
}
7.7 布尔类型 bool

作用:布尔类型代表真或假的值
bool类型只有两个值:

  • true (本质是1)
  • false (本质是0)

bool类型占1个字节大小

#include <iostream>
using namespace std;

int main()
{
    // 创建bool类型
    bool flag = true;
    cout << flag << endl; // 1
    flag = false;
    cout << flag << endl; // 0
    // 查看bool类型所占内存空间
    cout << sizeof(bool) << endl; // 1
    system("pause");
    return 0;
}
7.8 数据的输入

作用:用于从键盘获取数据
关键字:cin
语法:cin >> 变量

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int a = 0;
    // 整型
    cout << "Please input a: " << endl;
    cin >> a;
    cout << "a = " << a << endl;
    // 浮点型
    float f = 3.14f;
    cout << "please input f: " << endl;
    cin >> f;
    cout << "f = " << f << endl;
    // 字符型
    char ch = 'a';
    cout << "Please input ch: " << endl;
    cin >> ch;
    cout << "ch = " << ch << endl;
    // 字符串型
    string str = "hello";
    cout << "Please input str: " << endl;
    cin >> str;
    cout << "str = " << str << endl;
    // 布尔类型
    bool flag = false;
    cout << "Please input flag: " << flag << endl;
    cin >> flag; // 布尔类型只要非0都代表真
    cout << "flag = " << flag << endl;
    system("pause");
    return 0;
}
7.9 typedef

创建数据类型的别名:
(1)为名称复杂的类型创建别名,方便书写和记忆
(2)创建与平台无关的数据类型,提高程序兼容性
typedef 原数据类型名 别名;
C++11还可以用using关键字创建数据类型的别名
using 别名=原数据类型名;

#include <iostream>
using namespace std;

int main()
{
    typedef short int16_t;
    typedef int int32_t;
    typedef long long int64_t;
}

8 运算符

作用:用于执行代码的运算
在这里插入图片描述

8.1 算术运算符

在这里插入图片描述
两个小数是不可以做取模运算的
两个小数可以相除

8.2 赋值运算符

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // =
    int a = 10;
    a = 100;
    cout << a << endl;
    // +=
    a = 10;
    a += 2;
    cout << a << endl;
    // -=
    a = 10;
    a -= 2;
    cout << a << endl;
    // *=
    a = 10;
    a *= 2;
    cout << a << endl;
    // /=
    a = 10;
    a /= 2;
    cout << a << endl;
    // %=
    a = 10;
    a %= 2;
    cout << a << endl;
    system("pause");
    return 0;
}
8.3 比较运算符

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // ==
    int a = 10;
    int b = 20;
    cout << (a == b) << endl;
    // !=
    cout << (a != b) << endl;
    // >
    cout << (a > b) << endl;
    // <
    cout << (a < b) << endl;
    // >=
    cout << (a >= b) << endl;
    // <=
    cout << (a <= b) << endl;
    system("pause");
    return 0;
}
8.4 逻辑运算符

在这里插入图片描述
! && ||

#include <iostream>
using namespace std;

int main()
{
    // 非!
    // 在C++中, 除了0 都为真
    int a = 10;
    cout << !a << endl; // 0
    cout << !!a << endl;// 1
    // 与&&
    // &&: 两个条件都为真,结果才为真
    int b = 10;
    int c = 10;
    int d = 0;
    int e = 0;
    cout << (b && c) << endl;// 1
    cout << (b && d) << endl;// 0
    cout << (d && e) << endl;// 0
    // 或||
    // ||: 有一个真就是真,两个假就是假
    cout << (b || c) << endl; // 1
    cout << (b || d) << endl; // 1
    cout << (d || e) << endl; // 0
    system("pause");
    return 0;
}

9 程序流程结构

在这里插入图片描述

9.1 选择结构
9.1.1 if 语句

作用:执行满足条件的语句
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 单行if
    int score = 0;
    cout << "Please input score: " << endl;
    cin >> score;
    cout << "score = " << score << endl;
    if (score >= 650) // if后面不要加;
    {
        cout << "OK!!!!" << endl;
    }
    // 多行if
    if (score >= 650)
    {
        cout << "ok !!!!" << endl;
    }
    else
    {
        cout << "No !!!!" << endl;
    }
    // 多条件if
    if (score >= 650)
    {
        cout << "ok" << endl;
    }
    else if (score <= 250)
    {
        cout << "yes" << endl;
    }
    else
    {
        cout << "No" << endl;
    }
    // 嵌套if
    if (score >= 650)
    {
        if (score >= 700)
        {
            cout << "Beida" << endl;
        }
    }
    system("pause");
    return 0;
}

案例:三只小猪称体重
有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重

#include <iostream>
using namespace std;

int main()
{
    int A, B, C;
    cin >> A >> B >> C;
    if (A > B)
    {
        if (A > C)
        {
            cout << "A最重" << endl;
        }
        else
        {
            cout << "C最重" << endl;
        }
    }
    else
    {
        if (B > C)
        {
            cout << "B最重" << endl;
        }
        else
        {
            cout << "C最重" << endl;
        }
    }
    system("pause");
    return 0;
}
9.1.2 三目运算符

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

#include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int b = 20;
    int c = 0;

    c = (a > b ? a : b);
    cout << c << endl;
    // 在C++中三目运算符返回的是变量,可以继续赋值
    (a < b ? a : b) = 100;
    cout << a << ' ' << b << endl;
    system("pause");
    return 0;
}
9.1.3 switch语句

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // switch语句
    int score = 0;
    cin >> score;
    cout << score << endl;
    switch (score)
    {
        case 10:
            cout << "Classical" << endl;
            break;// 退出当前分支
        case 9:
            cout << "Classical" << endl;
            break;
        case 8:
            cout << "Very Good" << endl;
            break;
        default:
            cout << "common" << endl;
            break;
    }
    system("pause");
    return 0;
}

if 和 switch 区别
switch缺点:判断只能是整型或者字符型,不可以是一个区间
switch优点:结构清晰,执行效率高

9.2 循环结构
9.2.1 while
#include <iostream>
using namespace std;

int main()
{
    // while
    int num = 0;
    while (num < 10)// 0 ~ 9 写循环避免死循环
    {
        cout << num << endl;
        num++;
    }
    system("pause");
    return 0;
}

案例:猜数字
在这里插入图片描述
在这里插入图片描述

#include <iostream>
// time系统时间头文件包含
#include <ctime>
using namespace std;

int main()
{
    // 添加随机数种子 利用当前系统生成随机数,防止每次随机数都一样
    srand((unsigned int)time(NULL));
    // 系统生成随机数
    int num = rand()%100 + 1;// 0 ~ 99 -> 1 ~100
    // 玩家进行猜测
    int val = 0;
    while (1)
    {
        cin >> val;
        // 判断玩家的猜测 猜对,退出 猜错,提示猜的结果(过大,过小)

        if (val > num)
        {
            cout << "caice guoda" << endl;
        }
        else if (val < num)
        {
            cout << "guoxiao" << endl;
        }
        else
        {
            cout << "right" << endl;
            break;
        }
    }
    system("pause");
    return 0;
}
9.2.2 do…while
#include <iostream>
using namespace std;

int main()
{
    int num = 0;
    do {
        cout << num << endl;
        num++;
    }while (num < 10);
    system("pause");
    return 0;
}

do…while和while循环区别在于do…while会先执行一次循环语句
案例:水仙花数
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 100 ~ 999
    int num = 100;
    do {
        int a = 0;
        int b = 0;
        int c = 0;
        a = num % 10;     // 个位
        b = num / 10 % 10;// 十位
        c = num / 100;    // 百位
        if (a * a * a + b * b * b + c * c * c == num) // 如果是水仙花,才打印
        {
            cout << num << endl;
        }
        num++;
    }while (num < 1000);
    system("pause");
    return 0;
}
9.2.3 for循环语句
#include <iostream>
using namespace std;

int main()
{
//    for (int i = 0; i < 10; i++)
//    {
//        cout << i << endl;
//    }
    int i = 0;
    for ( ; ; )
    {
        if (i >= 10)
        {
            break;
        }
        i++;
        cout << i << endl;
    }
    system("pause");
    return 0;
}

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i <= 100; i++)
    {
        if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7)
        {
            cout << "lalala" << endl;
        }
        else
        {
            cout << i << endl;
        }
    }
    system("pause");
    return 0;
}
9.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;
}

案例:乘法口诀表

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i <=9; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cout << j << " * " << i << " = " << j * i << "   ";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}
9.3 break语句

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

  • switch条件语句中,终止case并跳出switch
  • 出现在循环语句中,作用是跳出当前的循环语句
  • 出现在嵌套循环中,跳出最近的内层循环语句
#include <iostream>
using namespace std;

int main()
{
    // switch
    int select = 0;
    cin >> select;
    switch (select)
    {
        case 1:
            cout << "common" << endl;
            break;
        case 2:
            cout << "middle" << endl;
            break;
        case 3:
            cout << "hard" << endl;
            break;
        default:
            break;
    }
    // 循环语句
    for (int i = 0; i < 10; i++)
    {
        if (i == 5)
        {
            break;
        }
        cout << i << endl;
    }
    // 嵌套循环语句
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (j == 5)
            {
                break; // 退出内层循环
            }
            cout << " * ";
        }
        cout << endl;
    }
    system("pause");
    return 0;
}
9.4 continue语句

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

#include <iostream>
using namespace std;

int main()
{
    // continue
    for (int i = 0; i <= 100; i++)
    {
        if (i % 2 == 0)
        {
            continue; // 可以筛选条件,执行到此不再往下执行,执行下一次循环
        }
        cout << i << endl;
    }
    system("pause");
    return 0;
}
9.5 goto语句

作用:无条件跳转语句
语法:goto 标记
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // goto语句
    cout << "1" << endl;
    cout << "2" << endl;
    goto FLAG;
    cout << "3" << endl;
    cout << "4" << endl;
    FLAG:
    cout << "5" << endl;
    system("pause");
    return 0;
}

10 数组

10.1 一维数组定义方式

特点:
(1)数组中每个数据元素都是相同的数据类型
(2)数组是由连续的内存位置组成的

#include <iostream>
using namespace std;

int main()
{
    // 数组定义
    int arr1[5];
    arr1[0] = 1;
    arr1[1] = 2;
    int arr2[5] = {10, 20, 30, 40, 50};
    for (int i = 0; i < 5; i++)
    {
        cout << arr2[i] << endl;
    }
    int arr3[] = {1, 2, 3, 4, 5}; // 定义数组的时候,必须有初始长度
    system("pause");
    return 0;
}

Tip:
(1) 数组名的命名规范与变量名命名规范一致,不要和变量重名
(2) 数组中下标是从0开始索引

10.2 一维数组 - 数组名

一维数组名称的用途:
1、可以统计整个数组在内存中的长度 sizeof(arr)
2、可以获取数组在内存中的首地址 cout << arr << endl;

#include <iostream>
using namespace std;

int main()
{
    // 可以统计整个数组在内存中的长度
    int arr[10] = {1, 2, 4,5, 6,7, 8, 9, 10, 11};
    cout << sizeof(arr) << endl; // 40 = 4 * 10
    cout << sizeof(arr[0]) << endl; // 4
    cout << sizeof(arr) / sizeof(arr[0]) << endl; // 10
    // 可以获取数组在内存中的首地址
    cout << arr << endl;
    cout << &arr[0] << endl;

    system("pause");
    return 0;
}

数组名是一个常量,不可以进行赋值操作
在这里插入图片描述

五只小猪称体重

#include <iostream>
using namespace std;

int main()
{
    // 五只小猪称体重
    int arr[5] = {300, 350, 200, 400, 250};
    int max = 0;
    for (int i = 0; i < 5; i++)
    {
        if(arr[i] > max) max = arr[i];
    }
    cout << max << endl;
    system("pause");
    return 0;
}

数组元素逆置

#include <iostream>
using namespace std;

int main()
{
    int arr[5] = {1, 3, 2, 5, 4};
    for (int i = 0; i < 5; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    int start = 0;
    int end = sizeof(arr) / sizeof(arr[0]) - 1;
    while (start < end)
    {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
    for (int i = 0; i < 5; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    system("pause");
    return 0;
}

冒泡排序
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    int arr[9] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
    for (int i = 0; i < 9; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    for (int i = 0; i < 9 - 1; i++)
    {
        for (int j = 0; j < 9 - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    for (int i = 0; i < 9; i++)
    {
        cout << arr[i] << ' ';
    }
    cout << endl;
    system("pause");
    return 0;
}
10.3 二维数组定义方式

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    // 二维数组定义方式
    // No.1
    int arr1[2][3];
    arr1[0][0] = 1;
    arr1[0][1] = 2;
    arr1[0][2] = 3;
    arr1[1][0] = 4;
    arr1[1][1] = 5;
    arr1[1][2] = 6;
    // No.2
    int arr2[2][3] =
            {
                    {1, 2, 3},
                    {4, 5, 6}
            };
    // No.3
    int arr3[2][3] = {1, 2, 3, 4, 5, 6};
    // No.4
    int arr4[][3] = {1,2,3,4,5,6,7,8,9};
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            cout << arr1[i][j] << ' ';
        }
    }
    system("pause");
    return 0;
}
10.4 二维数组名

(1)查看二维数组所占内存空间
(2)获取二维数组首地址

#include <iostream>
using namespace std;

int main()
{
    double 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[0][0] << endl;
    system("pause");
    return 0;
}

案例:
在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    /*
     * 0 300
     * 1 240
     * 2 210
     * */
    int score[3][3] =
    {
            {100, 100, 100},
            {90, 50, 100},
            {60, 70, 80}
    };
    for (int i = 0; i < 3; i++)
    {
        int sum = 0;
        for (int j = 0; j < 3; j++)
        {
            sum += score[i][j];
        }
        cout << i << ' ' << sum << endl;
    }
    system("pause");
    return 0;
}

11 函数

函数的声明和定义可以书写在一起,也可以分开,如果书写在一起,一般放在main函数的上面,如果分开,一般在main函数的上面声明,在main函数的下面定义

C++中定义变量的场景主要有五种:
1)在全部函数外面定义的是全局变量。
2)在头文件中定义的是全局变量。
3)在函数和语句块内部定义的是局部变量。
4)函数的参数是该函数的局部变量。
5)函数内部用static修饰的是静态局部变量。

当程序想要使用全局变量的时候应该先考虑使用static(考虑到数据安全性)

11.1 函数分文件编写

*.h:声名全局变量,函数声名,数据结构和类的声名
*.cpp:函数的定义、类的定义

11.2 在VS中调试程序

在这里插入图片描述

11.3 递归函数

递归函数:运行时调用自己的函数
Tip:递归函数中一定要有递归终止的条件,否则就是死递归
在这里插入图片描述

#include <iostream>
using namespace std;

int f(int x)
{
    if (x == 0) return 0; // 递归截止条件
    return x + f(x - 1);
}
int main()
{
    cout << "f(3)= " << f(3) << endl;
    system("pause");
    return 0;
}

12 指针

在这里插入图片描述
C++用运算符&获取变量在内存中的起始地址
指针变量简称指针,它是一种特殊的变量,专用于存放变量在内存中的起始地址

不管是整型、浮点型、字符型,还是其它的数据类型的变量,它的地址都是一个十六进制数。我们用整型指针存放整数型变量的地址;用字符型指针存放字符型变量的地址;用浮点型指针存放浮点型变量的地址,用自定义数据类型指针存放自定义数据类型变量的地址。

指针=&变量名
Tip:
(1) 对指针的赋值操作被称为“指向某变量”,被指向的变量数据类型称为“基类型”
(2) 指针的数据类型与基类型不符,编译会出现警告。但是,可以强制转换它们的类型

12.1 使用指针

指针用于函数的参数
值传递:函数的形参是普通变量
传地址:可以在函数中修改实参的值;减少内存拷贝,提升性能

12.2 用const修饰指针

(1)常量指针
语法:const 数据类型 *变量名

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

1.一般用于修饰函数的形参,表示不希望在函数里修改内存地址中的值
2.如果用于形参,虽然指向的对象可以改变,但这么做没有任何意义
3.如果形参的值不需要改变,建议加上const修饰,程序可读性更好
(2)指针常量
语法:数据类型 *const 变量名

指向的变量(对象)不可改变

1.定义的同时必须初始化
2.可以通过解引用的方法修改内存地址中的值
3.C++把指针常量做了一些特别的处理,叫引用
(3)常指针常量
语法:const 数据类型 *const 变量名;

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

13 void 关键字

用途:
(1)函数返回值用void
(2)函数的参数填void,表示函数不需要参数
(3)形参用void*, 表示接受任意数据类型的指针
Tip:
1.不能用void声名变量,它不能代表一个真实的变量,但是void* 可以
2.不能对void* 指针直接解引用(需要转换成其他类型的指针)
3.把其他类型的指针赋值给void*指针不需要转换,反之要转换

#include <iostream>
using namespace std;
void func(string name, void* p)
{
    cout << name << " " << p << endl;
    cout << name << " " << *(char*)p << endl;
}
int main()
{
    int a = 80;
    char b = 'X';
    cout << &a << endl;
    cout << &b << endl;
    
    func("a", &a);
    func("b", &b);
    return 0;
}

13 C++内存模型

内存主要分成四个区:栈、堆、数据段、代码段
在这里插入图片描述
栈和堆的主要区别:
(1)管理方式不同:栈是系统自动管理的,出作用域会被自动释放;堆需要手动释放,若程序中不释放,程序结束由操作系统回收
(2)空间大小不同:堆内存大小受限于物理内存空间;而栈小的可怜,一般只有8M(可以修改系统参数)
(3)分配方式不同
(4)分配效率不同
(5)是否产生碎片
(6)增长方向不同

14 动态分配内存new和delete

栈区的效率很高,但是空间很小;如果需要处理大量的数据,就必须使用堆区的内存

#include <iostream>
using namespace std;

int main()
{
    // 1 声名一个指针
    int *p;
    // 2 用new运算符向系统申请一块内存,让指针指向这块内存
    p = new int(5);
    // int *p = new int(5);
    // 3 通过对指针解引用的方法,像使用变量一样使用这块内存
    cout << "*p = " << *p << endl;
    *p = 8;
    cout << "*p = " << *p << endl;
    // 4 如果这块内存不用了,用delete运算符释放它
    delete p;
}

Tip:
(1)动态分配出来的内存没有变量名,只能通过操作指针来操作内存中的数据
(2)如果动态内存分配的内存不用了,必须用delete释放它,否则有可能用尽系统的内存
(3)动态分配的内存生命周期与程序相同,程序退出时,如果没有释放,系统自动回收
(4)就算指针的作用域失效,指向的内存也不会释放
(5)用指针跟踪已分配的内存,不能跟丢

15 二级指针

指针:用于存放普通变量的地址
二级指针:存放指针变量的地址
语法:数据类型** 指针名;
1.传递地址
2.存放动态分配的内存的地址

#include <iostream>
using namespace std;

int main()
{
    int a = 8;
    cout << "a = " << a << " " << &a << endl;
    int* p = &a;
    cout << "p = " << p << " " << &p << " " << *p << endl;
    int** h = &p;
    cout << "h = " << h << " " << &h << " " << *h << endl;
}

16 空指针

C/C++,用0或NULL都可以表示空指针。
声名指针后,在赋值之前,让他指向空,表示没有指向任何地址。
(1)后果:
1.对空指针解引用,程序会崩溃
2.如果对空指针使用delete运算符,系统忽略该操作,不会出现异常。所以,内存被释放后,也该把指针指向空
3.在函数中,应该判断形参是否为空指针的代码,目的是保证程序的健壮性
(2)C++11的nullptr
用0和NULL表示空指针会产生歧义,c++11建议用nullptr,(void*)0

注意:在Linux平台下,如果使用nullptr,编译需要加-std=c++11参数

#include <iostream>
using namespace std;

void func(int* no, string* str)
{
    if ((no == 0) || (str == 0)) return;
    cout << *no << " " << *str << endl;
}

int main()
{
    int* bh = 0;
    string* message = 0;
    func(bh, message);
    delete bh;
    delete message;
    return 0;
}

17 野指针

野指针:指针指向的不是一个有效合法的地址
访问野指针,可能会造成程序的崩溃
出现野指针的情况:
(1)指针未初始化
(2)指针指向了动态分配的内存,内存被释放后,指针不会置空,但是,指向的地址失效
(3)指针指向的变量已经超越变量的作用域,让指针指向了函数的局部变量,或者把函数的局部变量的地址作为返回值赋值给指针

#include <iostream>
using namespace std;

int* func()
{
    int a = 2;
    cout << a << ' ' << &a << endl;

    return &a;
}
int main()
{
//    int *p = new int(5);
//    cout << p << ' ' << *p << endl;
//    delete p;
//    cout << p << ' ' << *p << endl;
    int* p = func();
    cout << p << ' ' << *p << endl;

    return 0;
}

规避方法:
1.指针在定义的时候,如果没地方指,就初始化为nullptr
2.动态分配的内存被释放后,将其置为nullptr
3.函数不要返回局部变量的地址

野指针的危害比空指针大很多,访问野指针,可能会造成程序的崩溃。程序的表现是不稳定,增加了调试程序的难度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android开发APP显示头部Bar

Android开发显示头部Bar 需求&#xff1a; 显示如下图&#xff1a; 显示头部Bar&#xff0c;颜色也能自定义。 解决方案 这个修改是在如下三个文件里进行修改&#xff1a; 按顺序修改&#xff1a; themes.xml(night): <resources xmlns:tools"http://schemas.andr…

LeetCode(22)N 字形变换【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; N 字形变换 1.题目 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A …

3.6 Windows驱动开发:内核进程汇编与反汇编

在笔者上一篇文章《内核MDL读写进程内存》简单介绍了如何通过MDL映射的方式实现进程读写操作&#xff0c;本章将通过如上案例实现远程进程反汇编功能&#xff0c;此类功能也是ARK工具中最常见的功能之一&#xff0c;通常此类功能的实现分为两部分&#xff0c;内核部分只负责读写…

滚雪球学Java(09-2):Java中的关系运算符,你真的掌握了吗?

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

java“贪吃蛇”小游戏

基于java实现贪吃蛇小游戏&#xff0c;主要通过绘制不同的图片并以一定速度一帧一帧地在窗体上进行展示。 我是在javaSwing项目下创建了一个包 名字叫做&#xff1a;Snakes包 包下有一个启动类和一个设置代码的主界面两个类 代码主界面&#xff1a; 代码主界面主要讲解的是 …

2023年中国冲击波治疗仪市场发展趋势分析:未来市场增长空间更大[图]

冲击波在临床医学领域最早应用于体外冲击波碎石&#xff0c;在二十世纪八十年代末期&#xff0c;体外冲击波碎石技术开始被运用到骨科及康复理疗领域&#xff0c;经过十余年的临床研究&#xff0c;冲击波疗法日益完善&#xff0c;应用范围也日益扩大。冲击波作为一种介于保守疗…

【Linux】Linux进程间通信(二)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

【开源】基于Vue和SpringBoot的固始鹅块销售系统

项目编号&#xff1a; S 060 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S060&#xff0c;文末获取源码。} 项目编号&#xff1a;S060&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…

Elasticsearch:运用向量搜索通过图像搜索找到你的小狗

作者&#xff1a;ALEX SALGADO 你是否曾经遇到过这样的情况&#xff1a;你在街上发现了一只丢失的小狗&#xff0c;但不知道它是否有主人&#xff1f; 了解如何使用向量搜索或图像搜索来做到这一点。 通过图像搜索找到你的小狗 您是否曾经遇到过这样的情况&#xff1a;你在街…

【自留地】前端 - uniapp - Vue - React - Flutter

uniapp uniapp自用速查表 - 我的常用组件 uniapp自用速查表 - 我的常用组件_uniapp static/customicons.css-CSDN博客文章浏览阅读1.8k次。uniapp项目登录退出、全局变量与状态、本地存储、Tabbar标签栏、顶部导航栏、下拉刷新、触底刷新、Ajax交互、内置组件样式修改、自定义…

2018年五一杯数学建模C题江苏省本科教育质量综合评价解题全过程文档及程序

2019年五一杯数学建模 C题 江苏省本科教育质量综合评价 原题再现 随着中国的改革开放&#xff0c;国家的综合实力不断增强&#xff0c;中国高等教育发展整体已进入世界中上水平。作为一个教育大省&#xff0c;江苏省的本科教育发展在全国名列前茅&#xff0c;而江苏省13个地级…

Linux:进程替换和知识整合

文章目录 进程程序替换替换原理进程替换的理解 环境变量与进程替换命令行解释器实现逻辑 进程程序替换 前面已经学习了子进程的创建&#xff0c;但是子进程的创建不管怎么说&#xff0c;都是父进程代码的一部分&#xff0c;那么实际上如果想要子进程执行新的程序呢&#xff1f…

2023年中国脑电仿生电刺激仪发展趋势分析:智能化、精准化、使用感不断提高[图]

脑电仿生电刺激仪是一种通过直接数字频率合成技术合成脑电仿真低频生物电流&#xff0c;通过粘贴于两耳侧乳突、太阳穴或风池穴部位表皮的电极&#xff0c;用仿生物电自颅外无创伤地穿透颅骨屏障刺激小脑顶核区的电疗设备。此电流刺激可启动颅脑固有神经保护机制&#xff0c;改…

【MATLAB】史上最全的9种数据拟合算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有9种数据拟合算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一算法的代码&#xff08…

Odoo 15开发手册第六章 模型 - 结构化应用数据

本章我们更进一步学习模型层&#xff0c;以及如何使用模型来设计支撑应用的数据结构。我们会探讨可用的模型类型&#xff0c;以及在使用这些类型时如何定义强制进行数据验证的约束。 模型由支持不同数据类型的数据字段组成&#xff0c;一些字段类型支持定义模型间的关联。对于…

delphi电子处方流转 sm2 sm4(医院)

【delphi电子处方流转(医院) sm2 sm4】支持 就诊登记、电子处方上传预核验、处方处方医保电子签名、电子处方上传、电子处方撤销、电子处方信息查询、电子处方审核结果查询、电子处方取药结果查询、电子处方药品目录查询等功能。技术交流Q 648437169 下载链接&#xff1a;http…

4. hdfs高可用集群搭建

简介 前面把hadoop机器已经准备好了&#xff0c;zk集群搭建好了&#xff0c;本本就是开始搭建hdfs环境 hadoop环境准备 创建hadoop用户 三台机器都创建hadoop用户 useradd hadoop -d /home/hadoop echo "1q1w1e1r" | passwd --stdin hadoophadoop用户相互免密登…

语义检索系统【全】:基于milvus语义检索系统指令全流程-快速部署版

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

Linux操作系统基础 – 正则表达式快速入门

Linux操作系统基础 – 正则表达式快速入门 Linux Operating System Essentials - Introduction to Regular Expressions 通常在计算机科学领域&#xff0c;正则表达式被解释为对字符串操作的一种逻辑公式&#xff0c;即用事先定义好的特定字符及其组合组成所谓的“规则字符串”…

SpringBoot使用DevTools实现后端热部署

&#x1f4d1;前言 本文主要SpringBoot通过DevTools实现热部署的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&…