C语言 指针(特别篇)
本篇目录
- C语言 指针(特别篇)
- 内存地址
- 简要介绍C语言指针
- C语言的指针可以指向什么?
- 取地址符 ``&``(Address-of Operator)
- C语言中的 ``*`` 号运算符
- 示例集:
- 指向变量的指针
- 指向数组的指针
- 指向字符串的指针
- 二级指针
- 指针数组的数组名是一个二级指针
- 二维数组 || 矩阵 || 二级指针
- 指向结构体的指针
- 动态申请内存
- 指向函数的指针
- 指向函数的指针压入栈中实现递归调用
- 多级指针
- 三级指针
C语言 指针(特别篇)
C语言是一种十分重要的编程语言,广泛应用于计算机领域,尤其是操作系统、编译器、网络通信等方面。其中,指针是C语言中非常重要的概念和基础,本文主要介绍C语言中各种指针的用法。
内存地址
学好C语言指针的关键在于要深刻理解计算机中的内存地址。
计算机中的内存地址是指用来唯一标识存储单元的值。这些存储单元按照连续的方式构成了计算机的内存空间,每个存储单元可以存储一个字节(8位)的数据。
内存地址通常以十六进制表示,它们从0开始递增,直到最大地址。在32位系统中,最大地址为0xFFFFFFFF(4GB),而在64位系统中,最大地址可达到0xFFFFFFFFFFFFFFFF(18EB,1EB等于10^9GB)。
内存地址空间可分为以下几个部分:
-
代码段(Code Segment):
代码段存储程序的机器指令,也称为可执行代码。它是只读的,用来存放程序的指令集和常量数据。 -
数据段(Data Segment):
数据段存储程序的全局变量、静态变量和静态常量。它包含了已经初始化或默认初始化的数据,并且在程序运行期间不会发生变化。 -
BSS段(Block Started by Symbol):
BSS段存储未初始化的全局变量和静态变量。在程序加载时,BSS段的变量会自动被初始化为0或空指针。 -
堆(Heap):
堆是动态分配内存的区域,用于存储程序运行时动态申请的数据。在C语言中,通过函数如malloc()和free()来管理堆内存的分配与释放。 -
栈(Stack):
栈用于存储程序运行时的局部变量、函数参数和调用信息。栈是一种先进后出的数据结构,通过指针栈顶位置来实现栈帧的压入和弹出。 -
运行时堆栈:
运行时堆栈是保存函数调用过程中使用的局部变量、中间结果和返回地址的区域。每个函数调用都会在运行时创建一个新的堆栈帧,并在函数返回时销毁。
这些内存地址空间的划分使得程序能够有效地管理内存资源,并提供了不同类型数据的存储区域。对于程序员来说,理解计算机的内存地址模型是编写高效、可靠代码的基础之一。
简要介绍C语言指针
C语言的指针是一种变量,它可以存储内存地址作为值。指针的 本质是通过存储内存地址来提供对数据的间接访问和操作能力。
在计算机中,内存被划分成一个个存储单元,每个存储单元都有唯一的地址。在C语言中,指针允许我们将这些地址作为值存储起来,并通过指针来访问和修改所指向的内存单元中存储的数据。
指针的本质是在内存中存储的一个整数值,该值代表某个特定内存单元的地址。通过使用指针,我们可以直接操作内存中的数据,无需通过变量名来访问。这为程序员提供了更灵活、高效地处理数据的能力。
指针的特点有以下几点:
- 指针保存变量的内存地址,而不是变量的实际值。
- 通过指针可以直接读取或修改指向的内存单元中的数据。
- 指针在使用前需要进行初始化,即将指针指向特定地址。
- 可以通过指针进行数据的传递和共享,使得函数可以修改传入的变量的值。
总结起来,C语言的指针提供了一种强大的工具,能够在程序中灵活地操作内存中的数据。通过指针,我们可以实现动态内存管理、数组和字符串处理、数据结构的构建等功能。理解指针的本质能够帮助程序员更好地利用C语言进行开发和优化。C语言指针对于一些初学者来说可能很难,但是一旦掌握了C语言指针,将会大大提高编程的效率。
C语言的指针可以指向什么?
- 变量:指针可以指向不同类型的变量,包括整型、浮点型、字符型等。通过指针,可以访问和修改指向变量所存储的值。
- 数组元素:数组名本质上是指向数组首元素的指针,可以使用指针来遍历数组,访问和修改数组元素的值。
- 字符串:字符串实际上是由一系列字符组成的字符数组,在C语言中以空字符(‘\0’)结尾。可以使用指针来操作字符串,包括遍历、拷贝和连接等操作。
- 结构体:结构体是用户自定义的复合数据类型,可以包含多个不同类型的成员。指针可以指向结构体变量,允许通过指针访问和修改结构体中的成员。
- 动态分配的内存:C语言提供了动态内存管理的功能,可以使用指针来指向通过malloc()、calloc()等函数动态分配的内存块,并在不需要时释放该内存。
- 函数:在C语言中,函数也被视为一种特殊的数据类型。指针可以指向函数,称为函数指针。通过函数指针,可以调用相应的函数及传递函数作为参数。
取地址符 &(Address-of Operator)
在C语言中,取地址符(Address-of Operator)用于获取变量的地址。取地址符使用符号"&"表示,放置在变量名之前。
以下是取地址符的使用示例:
int num = 10;
int *ptr = # // 取得变量num的地址,并将其赋值给指针ptrprintf("变量num的地址:%p\n", &num);
printf("指针ptr存储的地址:%p\n", ptr);
C语言中的 * 号运算符
在C语言中,星号(*)是一元运算符,具有多种作用,取决于它所用的上下文。以下是星号运算符在C语言中的几种常见作用:
- 声明指针类型:在变量声明时,星号可以用作指针类型的标识符。例如,
int *ptr;声明了一个名为ptr的指向整型变量的指针。 - 解引用操作符(Dereference Operator):使用星号对指针进行解引用操作,可以访问指针所指向的内存地址存储的值。例如,
int x = *ptr;将会将指针ptr指向的内存地址的值赋给变量x。 - 定义函数指针:使用星号可以定义函数指针,用于存储函数的地址。例如,
int (*funcPtr)(int, int);定义了一个指向接受两个int类型参数并返回int类型值的函数的指针。 - 乘法运算符:星号还可以用于乘法运算,表示两个数相乘的结果,此时
*号就变成了二元运算符。例如,int result = a * b;将变量a和b相乘的结果赋给变量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的指针
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);elseprintf("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 函数中,我们使用三级指针来释放矩阵占用的内存。
请注意,在操作三级指针时需要小心管理内存,并确保正确地分配和释放内存,以避免内存泄漏和错误。
三级指针的应用
三维数组在编程中有许多应用场景,特别是在涉及到多维数据的存储和处理时非常有用。以下是一些常见的三维数组的应用示例:
-
三维图像处理:在计算机图形学和图像处理领域,三维数组经常用于表示和处理彩色图像或体积数据。图像可以被看作是由像素组成的二维阵列,而每个像素又包含红、绿、蓝(RGB)或其他颜色通道的值,这样就可以使用三维数组来表示图像数据。
-
三维空间建模:在三维建模、游戏开发和虚拟现实中,三维数组可以用于表示三维空间中的物体、场景或地形。例如,一个三维场景可以被分成一个网格,每个网格单元包含物体的属性、纹理信息或碰撞检测数据等。
-
多维物理模拟:在物理模拟和科学计算中,三维数组可以用于存储和更新三维空间中的物理量,如速度场、压力场或温度场。通过使用三维数组,可以对不同位置上的物理量进行存储和操作,并模拟复杂的物理过程。
-
数据立方体:三维数组还可以用于表示和分析包含多个维度的数据集,例如销售数据、气象数据或市场调查数据。这些数据通常以数据立方体(data cube)的形式进行分析和查询,其中三维数组的每个维度对应于数据集中的一个属性。
这些只是三维数组的一些常见应用示例,实际上,它们在各种领域和问题中都具有广泛的应用。使用三维数组时,需要理解索引和访问元素的方式,并根据具体的问题进行适当的操作和算法设计。
相关文章:
C语言 指针(特别篇)
本篇目录 C语言 指针(特别篇)内存地址简要介绍C语言指针C语言的指针可以指向什么?取地址符 &(Address-of Operator)C语言中的 * 号运算符示例集:指向变量的指针指向数组的指针指向字符串的指针二级指针指针数组的…...
【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(5月26日论文合集)
文章目录 一、检测相关(9篇)1.1 Energy-based Detection of Adverse Weather Effects in LiDAR Data1.2 Anomaly Detection with Conditioned Denoising Diffusion Models1.3 Mask Attack Detection Using Vascular-weighted Motion-robust rPPG Signals1.4 Improved Multi-Sca…...
网络编程与自动化(python)
20.1 网络编程与自动化概述 传统网络运维困境大家在日常的网络运维中是否遇到过如下问题: 设备升级:现网有数千台网络设备,你需要周期性、批量性地对设备进行升级。配置审计:企业年度需要对设备进行配置审计。例如要求所有设备开启sTelnet功能,以太网交换机配置生成树安全…...
有趣的数学 对称/非对称加密简史及数学原理一览
一、非对称加密简史 1、算法建立 对于任何想发送加密信息的人,另一个问题是如何让接收人知道这条信息一开始是如何加密的。对于像字母替换式密码这样的密码,问题在于,一旦窃听者知道了加密方案,后续的信息都可以轻松获取。 公钥加…...
AI大模型落地不远了!首个全量化Vision Transformer的方法FQ-ViT(附源代码)
点击蓝字 关注我们 关注并星标 从此不迷路 计算机视觉研究院 公众号ID|计算机视觉研究院 学习群|扫码在主页获取加入方式 论文地址:https://arxiv.org/pdf/2111.13824.pdf 项目代码:https://github.com/megvii-research/FQ-ViT 计…...
YouTubeDNN
这个youTubeDNN主要是工程导向,对于推荐方向的业界人士真的是必须读的一篇文章。它从召回到排序整个流程都做了描述,真正是在工业界应用的经典介绍。 作者首先说了在工业上YouTube视频推荐系统主要面临的三大挑战: 1.Scale(规模)࿱…...
面向对象的介绍和内存
学习面向对象内容的三条主线 • Java 类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类 • 面向对象的特征:封装、继承、多态、(抽象) • 其他关键字的使用…...
【数据可视化】Plotly Express绘图库使用
Plotly Express是一个基于Plotly库的高级Python可视化库。它旨在使绘图变得简单且直观,无需繁琐的设置和配置。通过使用Plotly Express,您可以使用少量的代码创建具有丰富交互性和专业外观的各种图表。以下是Plotly Express的一些主要特点和优势…...
小红书企业号限流原因有哪些,限流因素
作为企业、品牌在小红书都有官方账号,很多人将注册小红书企业号看作是获取品牌宣推“特权”的必行之举。事实真的如此吗,那为什么小红书企业号限流频发,小红书企业号限流原因有哪些,限流因素。 一、小红书企业号限流真的存在吗 首…...
1.6C++双目运算符重载
C双目运算符重载 C中的双目运算符重载指的是重载二元运算符,即有两个操作数的运算符,如加减乘除运算符“”、“-”、“*”和“/”等。 通过重载双目运算符,可以实现自定义类型的运算符操作。 比如可以通过重载加减运算符实现自定义类型的向…...
CDD诊断数据库的简单介绍
1. 什么是数据库? 数据库是以结构化方式组织的一个数据集合。 比如DBC数据库: Network nodes Display Rx Messages EngineState(0x123) 通过结构化的方式把网络节点Display里Rx报文EngineState(0x123)层层展开。这种方 式的好处是:层次清晰,结构分明,易于查找。 2. 什么…...
【笔试强训选择题】Day25.习题(错题)解析
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:笔试强训选择题 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!ÿ…...
Python心经(6)
目录 callable super type()获取对应类型 isinstance判断对象是否是某个类或者子类的实例 issubclass,判断对象是不是类的子孙类 python3的异常处理 反射: 心经第三节和第五节都写了些面向对象的,这一节补充一…...
MMPose安装记录
参考:GitHub - open-mmlab/mmpose: OpenMMLab Pose Estimation Toolbox and Benchmark. 一、依赖环境 MMPose 适用于 Linux、Windows 和 macOS。它需要 Python 3.7、CUDA 9.2 和 PyTorch 1.6。我的环境: Windows 11 Python 3.9 CUDA 11.6 PyTorch 1.13 …...
梯度下降优化
二阶梯度优化 1.无约束优化算法1.1最小二乘法1.2梯度下降法1.3牛顿法/拟牛顿法 2.一阶梯度优化2.1梯度的数学原理2.2梯度下降算法 3.二阶梯度优化梯度优化3.1 牛顿法3.2 拟牛顿法 1.无约束优化算法 在机器学习中的无约束优化算法中,除了梯度下降以外,还…...
一起看 I/O | 将 Kotlin 引入 Web
作者 / 产品经理 Vivek Sekhar 我们将在本文为您介绍 JetBrains 和 Google 的早期实验性工作。您可以观看今年 Google I/O 大会中的 WebAssembly 相关演讲,了解更多详情: https://youtu.be/RcHER-3gFXI?t604 应用开发者想要尽可能地在更多平台上最大限度地吸引用户…...
极致呈现系列之:Echarts地图的浩瀚视野(一)
目录 Echarts中的地图组件地图组件初体验下载地图数据准备Echarts的基本结构导入地图数据并注册展示地图数据结合visualMap展示地图数据 Echarts中的地图组件 Echarts中的地图组件是一种用于展示地理数据的可视化组件。它可以显示全国、各省市和各城市的地图,并支持…...
第四章 模型篇:模型训练与示例
文章目录 SummaryAutogradFunctions ()GradientBackward() OptimizationOptimization loopOptimizerLearning Rate SchedulesTime-dependent schedulesPerformance-dependent schedulesTraining with MomentumAdaptive learning rates optim.lr_scheluder Summary 在pytorch_t…...
利用人工智能模型学习Python爬虫
爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。 网络爬虫(又称为网页蜘蛛,网络机器人)是其中一种类型。 爬虫可以自动化浏览网络中的信息,当然浏览信息的时候需要按照我们制定的规则进行,这些规则我们称之为网络…...
.Net泛型详解
引言 在我们使用.Net进行编程的过程中经常遇到这样的场景:对于几乎相同的处理,由于入参的不同,我们需要写N多个重载,而执行过程几乎是相同的。更或者,对于几乎完成相同功能的类,由于其内部元素类型的不同&…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
