C语言 指针(特别篇)

news2024/12/29 13:46:12

本篇目录

  • C语言 指针(特别篇)
    • 内存地址
    • 简要介绍C语言指针
    • C语言的指针可以指向什么?
    • 取地址符 ``&``(Address-of Operator)
    • C语言中的 ``*`` 号运算符
    • 示例集:
      • 指向变量的指针
      • 指向数组的指针
      • 指向字符串的指针
      • 二级指针
        • 指针数组的数组名是一个二级指针
        • 二维数组 || 矩阵 || 二级指针
      • 指向结构体的指针
      • 动态申请内存
      • 指向函数的指针
          • 指向函数的指针压入栈中实现递归调用
      • 多级指针
        • 三级指针

C语言 指针(特别篇)

C语言是一种十分重要的编程语言,广泛应用于计算机领域,尤其是操作系统、编译器、网络通信等方面。其中,指针是C语言中非常重要的概念和基础,本文主要介绍C语言中各种指针的用法。


内存地址

学好C语言指针的关键在于要深刻理解计算机中的内存地址

计算机中的内存地址是指用来唯一标识存储单元的值。这些存储单元按照连续的方式构成了计算机的内存空间,每个存储单元可以存储一个字节(8位)的数据。

内存地址通常以十六进制表示,它们从0开始递增,直到最大地址。在32位系统中,最大地址为0xFFFFFFFF(4GB),而在64位系统中,最大地址可达到0xFFFFFFFFFFFFFFFF(18EB,1EB等于10^9GB)。

内存地址空间可分为以下几个部分:

  1. 代码段(Code Segment):
    代码段存储程序的机器指令,也称为可执行代码。它是只读的,用来存放程序的指令集和常量数据。

  2. 数据段(Data Segment):
    数据段存储程序的全局变量、静态变量和静态常量。它包含了已经初始化或默认初始化的数据,并且在程序运行期间不会发生变化。

  3. BSS段(Block Started by Symbol):
    BSS段存储未初始化的全局变量和静态变量。在程序加载时,BSS段的变量会自动被初始化为0或空指针。

  4. 堆(Heap):
    堆是动态分配内存的区域,用于存储程序运行时动态申请的数据。在C语言中,通过函数如malloc()和free()来管理堆内存的分配与释放。

  5. 栈(Stack):
    栈用于存储程序运行时的局部变量、函数参数和调用信息。栈是一种先进后出的数据结构,通过指针栈顶位置来实现栈帧的压入和弹出。

  6. 运行时堆栈:
    运行时堆栈是保存函数调用过程中使用的局部变量、中间结果和返回地址的区域。每个函数调用都会在运行时创建一个新的堆栈帧,并在函数返回时销毁。

这些内存地址空间的划分使得程序能够有效地管理内存资源,并提供了不同类型数据的存储区域。对于程序员来说,理解计算机的内存地址模型是编写高效、可靠代码的基础之一。


简要介绍C语言指针

C语言的指针是一种变量,它可以存储内存地址作为值。指针的 本质是通过存储内存地址来提供对数据的间接访问和操作能力

在计算机中,内存被划分成一个个存储单元,每个存储单元都有唯一的地址。在C语言中,指针允许我们将这些地址作为值存储起来,并通过指针来访问和修改所指向的内存单元中存储的数据。

指针的本质是在内存中存储的一个整数值,该值代表某个特定内存单元的地址。通过使用指针,我们可以直接操作内存中的数据,无需通过变量名来访问。这为程序员提供了更灵活、高效地处理数据的能力。

指针的特点有以下几点:

  1. 指针保存变量的内存地址,而不是变量的实际值。
  2. 通过指针可以直接读取或修改指向的内存单元中的数据。
  3. 指针在使用前需要进行初始化,即将指针指向特定地址。
  4. 可以通过指针进行数据的传递和共享,使得函数可以修改传入的变量的值。

总结起来,C语言的指针提供了一种强大的工具能够在程序中灵活地操作内存中的数据。通过指针,我们可以实现动态内存管理、数组和字符串处理、数据结构的构建等功能。理解指针的本质能够帮助程序员更好地利用C语言进行开发和优化。C语言指针对于一些初学者来说可能很难,但是一旦掌握了C语言指针,将会大大提高编程的效率。


C语言的指针可以指向什么?

  1. 变量:指针可以指向不同类型的变量,包括整型、浮点型、字符型等。通过指针,可以访问和修改指向变量所存储的值。
  2. 数组元素:数组名本质上是指向数组首元素的指针,可以使用指针来遍历数组,访问和修改数组元素的值。
  3. 字符串:字符串实际上是由一系列字符组成的字符数组,在C语言中以空字符(‘\0’)结尾。可以使用指针来操作字符串,包括遍历、拷贝和连接等操作。
  4. 结构体:结构体是用户自定义的复合数据类型,可以包含多个不同类型的成员。指针可以指向结构体变量,允许通过指针访问和修改结构体中的成员。
  5. 动态分配的内存:C语言提供了动态内存管理的功能,可以使用指针来指向通过malloc()、calloc()等函数动态分配的内存块,并在不需要时释放该内存。
  6. 函数:在C语言中,函数也被视为一种特殊的数据类型。指针可以指向函数,称为函数指针。通过函数指针,可以调用相应的函数及传递函数作为参数。

取地址符 &(Address-of Operator)

在C语言中,取地址符(Address-of Operator)用于获取变量的地址。取地址符使用符号"&"表示,放置在变量名之前。

以下是取地址符的使用示例:

int num = 10;
int *ptr = # // 取得变量num的地址,并将其赋值给指针ptr

printf("变量num的地址:%p\n", &num);
printf("指针ptr存储的地址:%p\n", ptr);

C语言中的 * 号运算符

在C语言中,星号(*)是一元运算符,具有多种作用,取决于它所用的上下文。以下是星号运算符在C语言中的几种常见作用:

  1. 声明指针类型:在变量声明时,星号可以用作指针类型的标识符。例如,int *ptr; 声明了一个名为ptr 的指向整型变量的指针。
  2. 解引用操作符(Dereference Operator):使用星号对指针进行解引用操作,可以访问指针所指向的内存地址存储的值。例如,int x = *ptr; 将会将指针 ptr 指向的内存地址的值赋给变量 x
  3. 定义函数指针:使用星号可以定义函数指针,用于存储函数的地址。例如,int (*funcPtr)(int, int); 定义了一个指向接受两个int类型参数并返回 int 类型值的函数的指针。
  4. 乘法运算符:星号还可以用于乘法运算,表示两个数相乘的结果,此时 * 号就变成了二元运算符。例如,int result = a * b; 将变量 ab 相乘的结果赋给变量 result

示例集:

指向变量的指针

int num = 10;
int *p;       // 定义一个整型指针
p = #     // 将指针p指向变量num的内存地址, & 为取地址符, 可以将变量的内存地址取出
printf("%d\n", *p);    // 输出变量num的值

在这里插入图片描述

指向数组的指针

C语言中,数组名本身就是指向数组首个元素的指针,可以通过指针访问整个数组的元素。

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;     // 数组名arr即是指向数组首个元素的指针
for (int i = 0; i < 5; i++) {
    printf("%d ", *(ptr + i));   // 输出数组元素
}

在这里插入图片描述

数组名本身就是一个指针:

int arr[5] = {1, 2, 3, 4, 5};
printf("数组的首地址为 %d\n", arr);
for (int i = 0; i < 5; i++) {
    printf("内存地址为 %d 中存储的数据为 %d\n", arr, *(arr + i));   // 输出数组元素
}

在这里插入图片描述

指向字符串的指针

#include <stdio.h>

int main() {
    char *name = "John"; // 指向字符常量"John"的指针
    printf("Name: %s\n", name); // 使用%s格式化输出字符串
    
    return 0;
}

在这里插入图片描述

#include <stdio.h>

int main() {
    char *fruits[] = {"Apple", "Banana", "Orange"}; // 字符串指针数组
    int i;

    for (i = 0; i < 3; i++) {
        printf("Fruit: %s\n", fruits[i]); // 使用循环遍历并输出每个字符串
    }

    return 0;
}

在这里插入图片描述

字符串的本质就是字符数组,也可以用指向数组的指针来操作字符串。

二级指针

二级指针 就是 指向 指针变量 的 指针。指针变量本质也是变量,只不过这个变量存储的是其他变量的内存地址罢了。既然是变量就有内存地址,所以还可以再定义一个指针变量,用再定义的指针变量来存储前面那个指针变量的内存地址,于是后定义的指针变量就指向了前面的指针变量。这个后定义的指针变量就是二级指针。

int num = 10;
int *p1 = &num;    // 指向变量num的指针
int **p2 = &p1;    // 指向指针p1的指针(二级指针)
printf("%d\n", **p2);    // 输出变量num的值

在这里插入图片描述

指针数组的数组名是一个二级指针

#include <stdio.h>
#include <string.h>
int main()
{
	int i;
	char *color[5]={"red","blue","yellow","green","black"};    //字符串数组, 或者说指针数组
	char **pc;    //二级指针
	char str[20];
	pc=color;
	printf("Input a color:");
	scanf("%s",str);
	for(i=0;i<5;i++)
		if(strcmp(str,*(pc+i))==0)
		 	break;
	if(i<5)
		printf("position:%d\n",i+1);
	else
		printf("Not Found\n");
	return 0;
}

二维数组 || 矩阵 || 二级指针

#include <stdio.h>
#include <stdlib.h>

// 函数:创建并初始化矩阵
int** createMatrix(int rows, int cols) {
    int** matrix = (int**)malloc(rows * sizeof(int*)); // 分配行指针数组的内存空间

    for (int i = 0; i < rows; i++) {
        matrix[i] = (int*)malloc(cols * sizeof(int)); // 分配每一行的内存空间

        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i + j; // 初始化矩阵元素的值
        }
    }

    return matrix;
}

// 函数:释放矩阵的内存空间
void freeMatrix(int** matrix, int rows) {
    for (int i = 0; i < rows; i++) {
        free(matrix[i]); // 释放每一行的内存空间
    }

    free(matrix); // 释放行指针数组的内存空间
}

// 函数:打印矩阵
void printMatrix(int** matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]); // 输出矩阵元素的值
        }
        printf("\n");
    }
}

int main() {
    int rows = 3, cols = 3;
    int** matrix = createMatrix(rows, cols);

    printf("Matrix:\n");
    printMatrix(matrix, rows, cols);

    freeMatrix(matrix, rows);

    return 0;
}

在这里插入图片描述

指向结构体的指针

typedef struct {
    char name[20];
    int age;
} Person;

Person person;
Person *ptr = &person;    // 指向结构体Person的指针
strcpy(ptr->name, "Tom"); // 修改结构体成员name的值
ptr->age = 25;            // 修改结构体成员age的值
printf("%s %d\n", ptr->name, ptr->age);   // 输出结构体成员的值

对于指向结构体的指针可以参考我的往期文章,内容很详细 : C语言结构体数组+结构体类型指针+指向结构体数组的指针+typedef类型

动态申请内存

动态申请内存的两个函数 malloc()calloc() 函数声明包含在 stdlib.h 头文件中。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int size;
    int *arr;

    printf("请输入数组大小:");
    scanf("%d", &size);

    // 动态分配内存
    arr = (int *)malloc(size * sizeof(int));

    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    // 初始化数组元素
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }

    // 打印数组元素
    printf("数组元素:");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }

    // 释放内存
    free(arr);

    return 0;
}

上述代码中,首先通过scanf函数获取用户输入的数组大小。然后使用malloc函数动态分配大小为size乘以sizeof(int)的内存空间,并将返回的指针赋值给整型指针变量arr。

接着,我们通过遍历数组对其元素进行初始化。最后,使用循环打印数组元素。

在程序末尾,使用free函数释放动态分配的内存空间,防止内存泄漏。

请注意,在使用完动态分配的内存后,一定要记得及时释放,以确保不会造成内存泄漏。

在这里插入图片描述

以下是一个使用 calloc 函数的例子:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int size;
    int *arr;

    printf("请输入数组大小:");
    scanf("%d", &size);

    // 使用calloc动态分配内存,并初始化为零
    arr = (int *)calloc(size, sizeof(int));

    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    // 打印数组元素
    printf("数组元素:");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }

    // 释放内存
    free(arr);

    return 0;
}

在上述代码中,我们先通过scanf函数获取用户输入的数组大小。然后使用calloc函数动态分配大小为size乘以sizeof(int)的内存空间,并将返回的指针赋值给整型指针变量arr。

由于使用了calloc函数,所分配的内存会被自动初始化为零。因此,在打印数组元素时,我们可以看到初始时它们都是零。

同样地,在程序末尾,使用free函数释放动态分配的内存空间,防止内存泄漏。

在这里插入图片描述

指向函数的指针

C语言中,函数其实也有一个入口地址。我们可以用指针来指向函数。函数入口地址是指函数在内存中的起始位置的地址。每个函数都有一个唯一的函数入口地址,它表示函数在可执行程序中的位置,让程序能够定位并调用该函数。

函数入口地址通常由编译器在编译阶段确定,并在链接器将各个模块合并成可执行程序时进行填充。当程序调用一个函数时,实际上是通过函数入口地址来跳转到该函数的代码执行处。

在C语言中,函数入口地址可以使用函数指针来表示和操作。函数指针是一个特殊类型的指针,它可以存储函数的入口地址,以便后续调用该函数。通过获取函数的入口地址,我们可以将其赋值给函数指针,并通过该指针间接调用函数。

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    int (*operation)(int, int); // 声明一个指向函数的指针

    operation = add; // 将add函数的地址赋值给指针
    printf("Result of addition: %d\n", operation(5, 3)); // 通过指针调用add函数

    operation = subtract; // 将subtract函数的地址赋值给指针
    printf("Result of subtraction: %d\n", operation(5, 3)); // 通过指针调用subtract函数

    operation = multiply; // 将multiply函数的地址赋值给指针
    printf("Result of multiplication: %d\n", operation(5, 3)); // 通过指针调用multiply函数

    return 0;
}

在这里插入图片描述

指向函数的指针压入栈中实现递归调用

当我们运行递归函数的时候,操作系统其实做的就是将每次调用的函数地址压入栈中。

在函数递归调用时,函数指针的压入栈中可以实现递归调用的原理。具体来说,当一个函数通过函数指针调用自身时,它需要将函数指针的值压入栈中,并保留其他必要的参数和局部变量。

下面是一个简单的示例代码,展示了利用函数指针实现递归调用的原理:

#include <stdio.h>

// 定义递归函数
int recursiveFunc(int n, int (*func)(int)) {
    if (n <= 0) {
        return 0;
    }
    
    // 调用函数指针指向的函数,并将结果与递归调用相加
    return func(n) + recursiveFunc(n - 1, func);
}

// 定义一个打印数字的函数
int printNumber(int num) {
    printf("%d ", num);
    return num;
}

int main() {
    int n = 5;
    
    // 将打印数字的函数指针作为参数传递,并压入栈实现递归调用
    int result = recursiveFunc(n, printNumber);
    
    printf("\n结果:%d\n", result);
    
    return 0;
}

在上面的例子中,我们定义了一个递归函数recursiveFunc,它接受两个参数:n表示递归的终止条件,func表示指向函数的指针。递归函数首先判断终止条件,如果满足则返回0;否则,调用函数指针指向的函数,并将结果与递归调用的结果相加。

我们还定义了一个打印数字的函数printNumber,它接收一个整数并在控制台上打印该数字。在main函数中,我们将打印数字的函数指针作为参数传递给递归函数,并将起始值设为5。

当程序运行时,递归函数会依次调用打印数字的函数,并在每次调用时打印当前的数字。最后,递归函数的结果被打印出来。

通过将指向函数的指针作为参数传递并压入栈,可以实现函数的递归调用。这种方法可以动态地指定需要执行的函数,并在函数执行过程中保持递归的状态。

请添加图片描述

多级指针

理论上指针的级数可以无限增长,但是通常没用应用的必要。记住一点,只有同级指针且指针指向的数据类型相同时,可以相互赋值

三级指针

#include <stdio.h>
#include <stdlib.h>

void printMatrix(int **matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

void createMatrix(int ***matrix, int rows, int cols) {
    *matrix = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; i++) {
        (*matrix)[i] = (int *)malloc(cols * sizeof(int));
        for (int j = 0; j < cols; j++) {
            (*matrix)[i][j] = i * cols + j;
        }
    }
}

void freeMatrix(int ***matrix, int rows) {
    for (int i = 0; i < rows; i++) {
        free((*matrix)[i]);
    }
    free(*matrix);
    *matrix = NULL;
}

int main() {
    int **matrix = NULL;
    int rows = 3;
    int cols = 3;

    createMatrix(&matrix, rows, cols);

    printf("Matrix:\n");
    printMatrix(matrix, rows, cols);

    freeMatrix(&matrix, rows);

    return 0;
}

在这个例子中,我们使用三级指针 int ***matrix 来操控矩阵。首先,在 createMatrix 函数中,我们通过传递指向指针的指针来分配内存并创建矩阵。然后,在 printMatrix 函数中,我们使用二级指针 int **matrix 来遍历和打印矩阵的元素。最后,在 freeMatrix 函数中,我们使用三级指针来释放矩阵占用的内存。

请注意,在操作三级指针时需要小心管理内存,并确保正确地分配和释放内存,以避免内存泄漏和错误。

三级指针的应用
三维数组在编程中有许多应用场景,特别是在涉及到多维数据的存储和处理时非常有用。以下是一些常见的三维数组的应用示例:

  1. 三维图像处理:在计算机图形学和图像处理领域,三维数组经常用于表示和处理彩色图像或体积数据。图像可以被看作是由像素组成的二维阵列,而每个像素又包含红、绿、蓝(RGB)或其他颜色通道的值,这样就可以使用三维数组来表示图像数据。

  2. 三维空间建模:在三维建模、游戏开发和虚拟现实中,三维数组可以用于表示三维空间中的物体、场景或地形。例如,一个三维场景可以被分成一个网格,每个网格单元包含物体的属性、纹理信息或碰撞检测数据等。

  3. 多维物理模拟:在物理模拟和科学计算中,三维数组可以用于存储和更新三维空间中的物理量,如速度场、压力场或温度场。通过使用三维数组,可以对不同位置上的物理量进行存储和操作,并模拟复杂的物理过程。

  4. 数据立方体:三维数组还可以用于表示和分析包含多个维度的数据集,例如销售数据、气象数据或市场调查数据。这些数据通常以数据立方体(data cube)的形式进行分析和查询,其中三维数组的每个维度对应于数据集中的一个属性。

这些只是三维数组的一些常见应用示例,实际上,它们在各种领域和问题中都具有广泛的应用。使用三维数组时,需要理解索引和访问元素的方式,并根据具体的问题进行适当的操作和算法设计。

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

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

相关文章

doris docker部署 1.2.4.1版本

目录 写在前面 镜像编译 准备工作 下载编译好的包 fe be 编辑初始化文件 fe be 编辑Dockerfile fe be 构建镜像 fe be 构建结果 镜像运行 fe be 修改配置 添加udf依赖 启动be 注册be 错误分析 写在前面 以下操作语句按顺序执行即可&#xff0c;如果需要…

泛型Generic

泛型 1. 介绍1.1 使用泛型的好处 2. 自定义泛型结构&#xff1a;泛型类、泛型接口&#xff1b;泛型方法2.1 泛型类、泛型接口2.2 泛型方法 3. 其他3.1 泛型在继承方面的体现3.2 通配符使用3.2.1 有限制的通配符 1. 介绍 把元素的类型设计成一个参数&#xff0c;这个类型参数叫…

数组6大排序算法

快速排序 核心算法&#xff1a; 1.取一个基准值&#xff08;一般是数组中间的元素&#xff09;&#xff0c;遍历数组&#xff0c;比基准值大的放右边&#xff0c;小的放左边&#xff0c;相等的则不动 2.分别创建三个数组来存储元素&#xff0c;最后将三个数组拼接起来 3.循…

Java替换Jar文件中的class文件方法

备份源文件 文件不重要的话可以不需要备份&#xff0c;线上环境务必备份方便回滚 mkdir bak cp test.jar bak 查看class文件所在目录 jar -tvf test.jar | grep Time.class 标红内容就是需要替换的class文件&#xff0c;如果有多个文件需要替换依次执行2&#xff0c;3步骤…

webSocket实时通信02——基于Spring【纯后端——JAVA】

这里是基于Spring整合websoket后来实现的实时通信&#xff0c;这里只有java的代码&#xff0c;通过在线网站 http://www.websocket-test.com/测试即可 1. 导包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

网络安全合规-职业发展路线

网络安全人才一将难求&#xff0c;缺口高达 95% 在以前&#xff0c;很多政企单位在进行 IT 部门及岗位划分时&#xff0c;只有研发和运维部门&#xff0c;安全人员直接归属到基础运维部&#xff1b;而现在&#xff0c;越来越多单位为了满足国家安全法律法规的要求&#xff0c;…

终极攻略!如何彻底防止Selenium被检测!

在使用Selenium进行爬虫时&#xff0c;许多朋友都会遇到各种反爬措施。 实际上&#xff0c;在绝大多数情况下&#xff0c;网站轻而易举地能够检测出你正在使用WebDriver而非标准浏览器。 本文将详细介绍如何有效防止检测的方法。 在一篇公众号文章《别去送死了。Selenium 与…

【重磅】智能未来 —— 人工智能与城乡规划的交叉对话(CSDN深圳城市开发者社区首场线下技术交流活动)

文章目录 活动主题活动海报活动时间活动地点互动有礼加入有礼赠书简介特别说明 活动主题 智能未来-人工智能与城乡规划的交叉对话 —— 以 AI 为核心主题&#xff0c;探索 AI 在 智慧城市、智能视频、智能编程 等重点领域的技术发展和实战落地。 活动海报 活动时间 2023.06…

加密与解密 调试篇 动态调试技术 (五)-WinDbg

windbg主要厉害的地方是在他可以对内核调试 并且本身微软的产品 对windows调试适配度够高 注意 windbg给出的图形操作并不好用 主要是使用命令行来进行操作 我们省略安装 直接进入调试 file 可以打开软件 可以附加也可以分析dump文件还可以进行内核和 远程调试内核调试分为…

招商基金资深架构师教你如何搭建统一监控平台

随着数字化进程的加速和业务的高速发展&#xff0c;系统的复杂程度日益升级&#xff0c;为确保业务系统的连续性和稳定性&#xff0c;越来越多的企业想要建设统一的监控平台&#xff0c;但却不知道从哪里开始着手。比如&#xff1a; 有些企业会直接将监控系统页面集成到统一监…

SpringBoot配置文件application.yml的理解

一、存放位置分类 1.当前项目根目录下的config目录下 2.当前项目的根目录下 3.resources目录下的config目录下 4.resources目录下 按照这上面的顺序&#xff0c;4个配置文件的优先级依次降低。 二、自定义存放位置和自定义命名 自定义存放位置和自定义配置文件命令和appl…

Python从Excel读取数据并使用Matplotlib绘制成二维图像

本课程实现使用 Python 从 Excel 读取数据&#xff0c;并使用 Matplotlib 绘制成二维图像。这一过程中&#xff0c;将通过一系列操作来美化图像&#xff0c;最终得到一个可以出版级别的图像。本课程对于需要书写实验报告&#xff0c;学位论文&#xff0c;发表文章&#xff0c;做…

Vue中的虚拟Dom,diff算法,以及diff的优化

virtual dom&#xff1a; 关键词&#xff1a; 1、 template 2、渲染函数 3、 vnode(virtual dom) 4、patch(diff算法) 5、view Vue.js通过编译将template 模板转换成渲染函数(render ) &#xff0c;执行渲染函数就可以得到一个虚拟节点树 VNode 虚拟节点&#xff1a;它可以代…

C++ 中的新成员

C 中的动态内存分配 C 中通过 new 关键字进行动态内存申请 C 中的动态内存申请是基于类型进行的 delete 关键字用于内存释放 new 关键字和 malloc 函数的区别 new 关键字是 C 的一部分 malloc 是由 C 库提供的函数 new 以具体类型为单位进行内存分配 malloc 以字节为单位…

Jenkins ——pipeline入门教程

一、什么是pipeline 什么是Pipeline&#xff1f;简单来说&#xff0c;就是一套运行于Jenkins上的工作流框架&#xff0c;将原本独立运行于单个或者多个节点的任务连接起来&#xff0c;实现单个任务难以完成的复杂发布流程&#xff08;实用场景&#xff1a;将多个Jenkins构建任…

最优化方法Python计算:一元函数搜索算法——二次插值法

已知连续函数 f ( x ) f(x) f(x)在 x ∗ x^* x∗近旁存在最优解 x 0 x_0 x0​。对博文《最优化方法Python计算&#xff1a;连续函数的单峰区间计算》讨论的 f ( x ) f(x) f(x)单峰区间的包围算法稍加修改&#xff0c;可算得 f ( x ) f(x) f(x)包含 x 0 x_0 x0​的单峰区间 [ a …

pandas---删除重复行、映射、异常值检测与过滤、抽样

1. 删除重复行 使用duplicated()函数检测重复的行。 返回布尔类型的Series对象&#xff0c;每个元素对应一行&#xff0c;如果该行不是第一次出现&#xff0c;则元素为True。 def make_df(indexs, columns): data [[str(j)str(i) for j in columns] for i in indexs]df …

中国人民大学与加拿大女王大学金融硕士——用更长远的眼光,展望未来

职场中遇到瓶颈&#xff0c;大家都迫切希望改变自己所处的环境&#xff0c;但却不愿意改变自己&#xff0c;所以他们自己仍然是被束缚的。如果一个人不能够从自我拷问的状态中解脱出来&#xff0c;他就永远也不可能实现自己心中的目标。我们要用更长远的眼光去展望未来&#xf…

NAVIGATE 领航者峰会:记忆科技携手新华三,以存储创新释放数据价值

近日&#xff0c;由紫光集团和新华三集团主办的2023 NAVIGATE 领航者峰会在杭州举行。本届峰会的主题为“精耕务实&#xff0c;为时代赋智慧”&#xff0c;围绕该主题&#xff0c;国内外数千名技术领导者汇聚一堂&#xff0c;探讨数字经济的创新未来。作为IT硬件领域的重要厂商…

vue + g6 实现树级结构(compactBox 紧凑树)

G6文档 自定义节点 G6.registerNode("dom-node",{draw: (cfg, group) > {let str <div classitem-box catalog-node ${cfg.isSelected ? "is-selected" : ""} ${cfg.status}-box οnclickhandleDetail("${cfg.id}") id&quo…