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

嵌入式C语言:二维数组

目录

一、二维数组的定义

二、内存布局

2.1. 内存布局特点

2.2. 内存布局示例

2.2.1. 数组元素地址

2.2.2. 内存布局图(简化表示)

2.3. 初始化对内存布局的影响

三、访问二维数组元素

3.1. 常规下标访问方式

3.2. 通过指针访问

3.2.1. 指向数组首元素的指针

3.2.2. 指向单行元素的指针

3.2.3. 指针数组访问方案(一种特殊的间接方式)

3.2.4. 动态二维数组与指针

3.3. 使用宏定义来简化访问

四、应用场景

4.1. 图像处理

4.2. 矩阵运算

4.3. 传感器数据采集与处理(矩阵形式的传感器阵列)

4.4. 游戏开发(简单的嵌入式游戏)

五、注意事项

5.1. 数组大小与内存限制

5.2. 数组越界访问

5.3. 作为函数参数传递

5.4. 初始化与赋值操作

5.5. 其它


在嵌入式 C 语言中,二维数组是一种非常有用的数据结构,用于存储和处理按行和列组织的数据。

一、二维数组的定义

在C语言中,二维数组的定义遵循以下语法结构:

数据类型 数组名[行数][列数];
int array[3][4];  // 声明一个3行4列的二维数组

定义了一个整数类型的二维数组array,包含3行4列,总共能存储12个整数。这些整数在内存中是线性排列的,即先填满第一行,再接着填充第二行,以此类推。

二、内存布局

二维数组在内存中的布局是按一维线性方式排列的,但逻辑上它呈现二维结构,即有行和列的概念。

2.1. 内存布局特点

  • 连续存储:二维数组的所有元素在内存中都是连续存储的,没有间隔或空隙。

  • 按行存储:二维数组通常是按行优先(row-major order)存储的。意味着数组的第一行完全存储在内存中,紧接着是第二行,依此类推。

  • 元素地址计算:给定一个二维数组array[rows][cols]和一个元素array[i][j],其内存地址可以通过以下方式计算(假设数组的起始地址为base_address,且每个元素的大小为element_size):

address_of_element = base_address + (i * cols + j) * element_size

2.2. 内存布局示例

int array[3][4]为例,假设每个整数元素占4个字节,且数组的起始地址为2000(仅为示例,实际地址由操作系统分配)。

2.2.1. 数组元素地址

  • array[0][0]的地址为2000。
  • array[0][1]的地址为2004(因为每个元素占4个字节)。
  • array[0][2]的地址为2008。
  • array[0][3]的地址为2012。
  • array[1][0]的地址为2016(跳过了第一行的4个元素)。
  • 以此类推,array[2][3]的地址为2044。

2.2.2. 内存布局图(简化表示)

地址	元素
2000	array[0][0]
2004	array[0][1]
2008	array[0][2]
2012	array[0][3]
2016	array[1][0]
2020	array[1][1]
2024	array[1][2]
2028	array[1][3]
2032	array[2][0]
2036	array[2][1]
2040	array[2][2]
2044	array[2][3]

用代码来验证这种布局,可以通过指针运算:

#include <stdio.h>int main() {int arr[3][4];int *p = (int *)arr;for (int i = 0; i < 3 * 4; i++) {p[i] = i;}for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {printf("arr[%d][%d] = %d, address: %p\n", i, j, arr[i][j], &arr[i][j]);}}return 0;
}

 

先把二维数组当成一维数组,用指针给所有元素赋值,之后再用二维数组的常规访问方式输出每个元素及其地址。可以清晰看到,随着循环变量的推进,元素地址是连续递增的,充分证明了按行优先的存储特性。

这种内存布局的优势在于,访问同一行元素时,由于内存连续性,缓存命中率更高,能够加快数据访问速度。而且在进行一些底层算法,例如矩阵遍历、图像像素点扫描时,了解这种布局可以简化指针运算,高效处理数组元素 。 

2.3. 初始化对内存布局的影响

二维数组的初始化不会影响其内存布局方式,但会决定数组元素的初始值。

  • 完全初始化:如果提供了足够的初始值来填充整个数组,那么这些值将按行顺序存放在内存中。

int array[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};
  • 部分初始化:如果只提供了部分初始值,那么未初始化的元素将被自动初始化为0(对于静态存储类型的数组)。这些0值也将按顺序存放在内存中。

int array[3][4] = {{1, 2},{3}
};
// 相当于:
// int array[3][4] = {
//     {1, 2, 0, 0},
//     {3, 0, 0, 0},
//     {0, 0, 0, 0}
// };

三、访问二维数组元素

3.1. 常规下标访问方式

使用下标访问二维数组元素是最直接且常见的方法:

array[i][j];  // i表示行索引,j表示列索引

索引都是从 0 开始计数。例如,对于前面定义的 array数组,要访问第二行第三列的元素,就用 matrix[1][2],它的值是 6。 

代码示例

#include <stdio.h>int main() {int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};// 访问第二行第三列的元素int element = matrix[1][2];printf("Element at row 1, column 2: %d\n", element); // 输出: 7return 0;
}

 

在嵌入式系统中,这种精准访问常用于读取传感器矩阵数据、操控显示屏像素点等场景,每个元素对应一个物理量或者像素信息。

3.2. 通过指针访问

3.2.1. 指向数组首元素的指针

当我们有一个二维数组时,如int array[3][4];,可以定义一个指向其首元素的指针,即指向第一行第一个元素的指针:

int (*ptr)[4] = array; // ptr 是一个指向包含4个int元素的数组的指针

此时,ptr 可以被用来访问二维数组的元素。例如,ptr[i][j] 相当于 array[i][j]。这里,ptr[i] 是一个指向第 i 行第一个元素的指针(类型也是 int (*)[4]),然后 [j] 用于访问该行的第 j 个元素。

例如:

#include <stdio.h>int main() {int arr[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int (*q)[4];q = arr;for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {// 通过指向行的指针访问元素并打印printf("%d ", (*(q + i))[j]);}printf("\n");}return 0;
}

 

3.2.2. 指向单行元素的指针

另一种方法是定义一个指向 int 的指针,并让它指向二维数组的第一个元素。这种方法需要更复杂的索引计算来访问特定的元素:

int *ptr = &array[0][0]; // ptr 是一个指向 int 的指针

要访问 array[i][j],我们需要计算正确的偏移量:

int value = *(ptr + i * 4 + j); // 假设每行有4个元素

这里的 i * 4 + j 计算了从数组开始到 array[i][j] 的元素偏移量(假设数组是按行存储的,且每行有4个元素)。

例如:

#include <stdio.h>int main() {int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int *p = &matrix[0][0]; // 指向二维数组的第一个元素// 访问第二行第三列的元素int element = *(p + 1*4 + 2); // 1*4 + 2 是根据二维数组的内存布局计算出的偏移量printf("Element at row 1, column 2 (via pointer): %d\n", element); // 输出: 7return 0;
}

 

3.2.3. 指针数组访问方案(一种特殊的间接方式)

指针数组的构建:可以创建一个指针数组,其中每个指针指向二维数组的每一行。例如,对于int arr[3][4];,可以定义

int *row_pointers[3];

然后通过循环初始化每个指针,如

for (int i = 0; i < 3; i++) {row_pointers[i] = arr[i];}

这样,row_pointers数组中的每个元素就分别指向了arr的每一行。

元素访问方式:要访问二维数组中的元素arr[i][j],可以使用

*(row_pointers[i] + j)

这里row_pointers[i]获取到指向第i行的指针,然后+ j进行列偏移,最后通过解引用*获取元素的值。

#include <stdio.h>
int main() {int arr[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int *row_pointers[3];for (int i = 0; i < 3; i++) {row_pointers[i] = arr[i];}for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {// 通过指针数组访问元素并打印printf("%d ", *(row_pointers[i] + j));}printf("\n");}return 0;
}

 

3.2.4. 动态二维数组与指针

如果二维数组的大小是动态的,我们通常使用动态内存分配(如 malloc)来创建它,并使用指针来访问它。例如:

int rows = 3, cols = 4;
int **array = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {array[i] = malloc(cols * sizeof(int));
}// 访问元素
array[i][j] = some_value;// 释放内存
for (int i = 0; i < rows; i++) {free(array[i]);
}
free(array);

在这种情况下,array 是一个指向指针的指针(即 int **),每个 array[i] 都是一个指向第 i 行第一个元素的指针(即 int *)。

使用指针访问的优势: 在嵌入式系统中,尤其是在资源有限的情况下,通过指针访问二维数组可以更灵活地操作内存。例如,在一些实时数据处理场景中,通过指针可以快速地遍历数组元素,减少不必要的下标计算开销。同时,在与硬件寄存器或者内存映射 I/O 设备交互时,指针访问方式可以更好地适应底层硬件的地址访问要求。 

3.3. 使用宏定义来简化访问

为了方便和安全地访问二维数组元素,可以使用宏定义来封装访问逻辑。

宏定义与代码示例

#include <stdio.h>
#include <assert.h>// 辅助函数,用于访问二维数组的元素,并进行边界检查
static inline int safe_access_element(int *array, int row, int column, int width, int height) {assert(row >= 0 && row < height && column >= 0 && column < width);return array[row * width + column];
}// 宏,用于方便地从二维数组名获取数组指针(因为数组名在大多数情况下会退化为指针)
#define ACCESS_ARRAY(array) (&(array)[0][0])int main() {int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int rows = 3;int cols = 4;// 使用函数安全地访问第二行第三列的元素int element = safe_access_element(ACCESS_ARRAY(matrix), 1, 2, cols, rows);printf("Element at row 1, column 2 (via function): %d\n", element); // 输出: 7// 尝试访问一个无效的索引(这将触发断言失败)// int invalidElement = safe_access_element(ACCESS_ARRAY(matrix), 3, 2, cols, rows); // 这行会触发断言错误return 0;
}

 

使用宏定义ACCESS_ELEMENT可以简化二维数组元素的访问,同时提高代码的可读性和可维护性。在需要频繁访问二维数组元素的嵌入式应用程序中,这种方法特别有用。

四、应用场景

在嵌入式C语言中,二维数组作为一种重要的数据结构,具有广泛的应用场景。

4.1. 图像处理

  • 图像存储:在嵌入式图像采集与处理系统中,二维数组是存储图像像素数据的理想选择。例如,一个简单的灰度图像可以用一个二维数组unsigned char image[height][width];来存储,其中height表示图像的高度(行数),width表示图像的宽度(列数),而unsigned char类型的元素可以存储每个像素的灰度值(通常范围是 0 - 255)。
  • 图像滤波:二维数组可用于实现图像滤波算法。例如,在一个简单的均值滤波算法中,对于图像中的每个像素,需要访问其周围像素的值来计算平均值。可以通过二维数组来遍历图像,如下所示:
void mean_filter(unsigned char image[height][width]) {unsigned char filtered_image[height][width];for (int i = 1; i < height - 1; i++) {for (int j = 1; j < width - 1; j++) {int sum = 0;for (int m = -1; m <= 1; m++) {for (int n = -1; n <= 1; n++) {sum += image[i + m][j + n];}}filtered_image[i][j] = sum / 9;}}// 将滤波后的图像数据复制回原始数组或进行其他操作for (int i = 1; i < height - 1; i++) {for (int j = 1; j < width - 1; j++) {image[i][j] = filtered_image[i][j];}}
}
  • 图像边缘检测:在边缘检测算法(如 Sobel 算子)中,也需要使用二维数组来存储图像数据并进行卷积运算。通过对图像的水平和垂直方向分别进行卷积,可以计算出每个像素的梯度值,从而确定图像的边缘位置。

4.2. 矩阵运算

  • 科学计算与工程应用:在嵌入式系统的科学计算和工程应用中,经常会遇到矩阵运算。例如,在机器人运动学和动力学计算中,需要使用二维数组来表示变换矩阵。假设一个机器人手臂的正向运动学计算,需要将各个关节的旋转矩阵相乘得到末端执行器相对于基座的位姿矩阵。可以定义二维数组来存储这些矩阵,如下所示:
float joint1_matrix[4][4];
float joint2_matrix[4][4];
// 初始化关节矩阵
//...
float end_effector_matrix[4][4];
matrix_multiply(end_effector_matrix, joint1_matrix, joint2_matrix);

其中matrix_multiply函数用于实现矩阵乘法运算,通过嵌套循环来访问二维数组中的元素进行计算。

  • 数字信号处理中的矩阵运算:在数字信号处理领域,如快速傅里叶变换(FFT)的矩阵形式实现,也会用到二维数组。FFT 算法可以通过矩阵乘法来高效地计算信号的频谱,二维数组用于存储变换矩阵和信号数据,方便进行运算和中间结果的存储。

4.3. 传感器数据采集与处理(矩阵形式的传感器阵列)

  • 温度传感器阵列:在环境监测系统中,可能会使用一个二维的温度传感器阵列来获取空间温度分布。可以用二维数组来存储传感器数据,如下所示:
int temperature_array[num_rows][num_cols];
// 读取每个传感器的数据并存储到二维数组中
for (int i = 0; i < num_rows; i++) {for (int j = 0; j < num_cols; j++) {temperature_array[i][j] = read_temperature_sensor(i, j);}
}

之后,可以对这些数据进行分析,如查找温度异常点、计算平均温度等操作。

  • 压力传感器阵列:在一些触觉传感器系统或汽车轮胎压力监测系统中,使用压力传感器阵列来获取压力分布信息。二维数组可以很好地存储这些数据,并用于计算压力中心、压力变化趋势等参数,为后续的控制或监测提供数据支持。

4.4. 游戏开发(简单的嵌入式游戏)

  • 游戏地图存储与遍历:在简单的嵌入式游戏(如基于小型嵌入式设备的迷宫游戏或棋类游戏)中,二维数组可以用于存储游戏地图。例如,一个迷宫游戏可以用二维数组char maze[height][width];来存储,其中maze[i][j]的值可以表示该位置是墙壁(例如用'#'表示)、通道(用'.'表示)还是其他特殊元素(如宝藏、怪物等)。在游戏中,角色在迷宫中的移动可以通过遍历二维数组来实现,根据当前位置和移动方向来更新角色的位置,并检查是否遇到墙壁或其他特殊元素。
  • 游戏状态存储与更新:对于一些棋类游戏,如简单的井字棋游戏,可以用二维数组来存储棋盘状态。例如,int tic - tac - toe_board[3][3];,数组元素的值可以表示该位置是空白(0)、玩家 1 的棋子(1)还是玩家 2 的棋子(2)。在游戏过程中,通过更新二维数组中的元素来记录游戏状态,并根据游戏规则检查是否有玩家获胜或游戏是否平局。

五、注意事项

在嵌入式C语言编程中,二维数组是一种强大的数据结构,但使用时需要注意以下几点,以确保程序的稳定性和安全性。

5.1. 数组大小与内存限制

  • 内存占用:二维数组占用连续的内存空间,其大小由元素类型、行数和列数共同决定。在内存资源有限的嵌入式系统中,定义大型二维数组可能会导致内存不足,因此需要仔细考虑数组大小是否符合系统的内存预算。
  • 栈空间限制:在函数内部定义的二维数组通常占用栈空间。栈空间大小在嵌入式系统中也是有限的,过大的二维数组可能会导致栈溢出。因此,可以考虑将二维数组定义为全局变量或使用动态内存分配来解决。

5.2. 数组越界访问

  • 问题描述:C语言不会对数组下标进行边界检查,很容易出现数组越界的情况。越界访问可能会导致数据损坏、程序崩溃或产生错误的计算结果。
  • 预防措施:在编写代码时要格外小心,通过添加适当的条件判断来确保下标在合法范围内。良好的代码注释和代码风格也有助于减少越界访问的错误。

5.3. 作为函数参数传递

  • 参数声明要求:当二维数组作为函数参数传递时,除了第一维(行数)可以不指定大小外,其他维度(列数)必须指定大小。因为编译器需要知道列数才能正确地计算元素的偏移量。
  • 传递方式的理解:二维数组在函数中实际上被看作是一个指向数组首元素的指针。在编写函数时,需要清楚这种传递方式,以正确地访问和操作二维数组元素。

5.4. 初始化与赋值操作

  • 初始化方式:二维数组可以在定义时进行初始化,初始化方式有多种,包括按行初始化和不按行初始化。在初始化时要注意确保提供的初始值数量和数组大小相匹配,避免出现未初始化的元素。
  • 赋值操作:对二维数组元素进行赋值时,需要逐个元素赋值,不能像对普通变量那样整体赋值。可以通过循环或逐个指定元素的方式进行赋值。

5.5. 其它

  • 访问效率:由于二维数组是按行存储的,因此访问同一行的元素时通常比访问不同行的元素更高效。在编写代码时,可以尽量利用这一特性来提高程序的性能。
  • 指针操作:指针操作是常见的。了解二维数组的内存布局有助于正确地进行指针运算和数组访问。

综上所述,二维数组在内存中的布局是按一维线性方式排列的,但逻辑上呈现二维结构。在C语言中,二维数组通常是按行存储的。了解二维数组的内存布局有助于更好地管理内存和优化程序性能。

相关文章:

嵌入式C语言:二维数组

目录 一、二维数组的定义 二、内存布局 2.1. 内存布局特点 2.2. 内存布局示例 2.2.1. 数组元素地址 2.2.2. 内存布局图&#xff08;简化表示&#xff09; 2.3. 初始化对内存布局的影响 三、访问二维数组元素 3.1. 常规下标访问方式 3.2. 通过指针访问 3.2.1. 指向数…...

计算机网络期末复习(知识点)

概念题 在实际复习之前&#xff0c;可以看一下这个视频将网络知识串一下&#xff0c;以便更好地复习&#xff1a;【你管这破玩意叫网络&#xff1f;】 网络规模的分类 PAN&#xff08;个人区域网络&#xff09;&#xff1a;用于个人设备间的连接&#xff0c;如手机与蓝牙耳机…...

LeetCode:3298. 统计重新排列后包含另一个字符串的子字符串数目 II(滑动窗口 Java)

目录 3298. 统计重新排列后包含另一个字符串的子字符串数目 II 题目描述&#xff1a; 实现代码与解析&#xff1a; 滑动窗口 原理思路&#xff1a; 3298. 统计重新排列后包含另一个字符串的子字符串数目 II 题目描述&#xff1a; 给你两个字符串 word1 和 word2 。 如果…...

【SpringAOP】Spring AOP 底层逻辑:切点表达式与原理简明阐述

前言 &#x1f31f;&#x1f31f;本期讲解关于spring aop的切面表达式和自身实现原理介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &am…...

es 3期 第23节-运用Pipeline实现二转聚合统计

#### 1.Elasticsearch是数据库&#xff0c;不是普通的Java应用程序&#xff0c;传统数据库需要的硬件资源同样需要&#xff0c;提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库&#xff0c;不是关系型数据库&#xff0c;不具备严格的ACID事务特性&#xff…...

T-SQL语言的编程范式

T-SQL编程范式探析 引言 随着信息技术的迅猛发展&#xff0c;数据库在各个行业的应用日益广泛。在众多数据库管理系统中&#xff0c;SQL Server以其高性能和易用性受到广泛欢迎。T-SQL&#xff08;Transact-SQL&#xff09;是SQL Server的扩展版本&#xff0c;是一种用于查询…...

【ArcGIS微课1000例】0137:色彩映射表转为RGB全彩模式

本文讲述ArcGIS中,将tif格式的影像数据从色彩映射表转为RGB全彩模式。 参考阅读:【GlobalMapper精品教程】093:将tif影像色彩映射表(调色板)转为RGB全彩模式 文章目录 一、色彩映射表预览二、色彩映射表转为RGB全彩模式一、色彩映射表预览 加载配套数据包中的0137.rar中的…...

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…...

网络安全核心目标CIA

网络安全的核心目标是为关键资产提供机密性(Confidentiality)、可用性(Availablity)、完整性(Integrity)。作为安全基础架构中的主要的安全目标和宗旨&#xff0c;机密性、可用性、完整性频频出现&#xff0c;被简称为CIA&#xff0c;也被成为你AIC&#xff0c;只是顺序不同而已…...

hive迁移后修复分区慢,怎么办?

我有1个30TB的分区表&#xff0c;客户给的带宽只有600MB&#xff0c;按照150%的耗时来算&#xff0c;大概要迁移17小时。 使用hive自带的修复分区命令&#xff08;一般修复分区比迁移时间长一点&#xff09;&#xff0c;可能要花24小时。于是打算用前面黄大佬的牛B方案。 Hive增…...

一块钱的RISC-V 32位芯片

‍‍ ‍‍之前跟一个朋友聊天&#xff0c;说以后的芯片一定是越来越趋向于定制化&#xff0c;比如我们需要一个ADC芯片&#xff0c;这颗ADC芯片需要有串口功能&#xff0c;那就只开发一颗这样的芯片就好了&#xff0c;其他的功能都可以裁剪掉。 ➵➵➵➵➵➵➵➵➵➵➵➵➵➵➵…...

Linux常用指令

目录 1 概述2 指令2.1 简单指令2.2 解压缩2.2.1 tar.bz2和tar.gz2.2.2 单独bz22.2.3 zip2.2.4 7z 2.3 网卡操作 1 概述 本章主要是记录一些日常用到的Linux指令&#xff0c;方便自己忘记的时候查找&#xff0c;也为有需要的人提供参考。 2 指令 2.1 简单指令 指令解释cat /…...

车载音频开发(二):对音频数据作音量调节

通过前一个章节打下的基础车载音频开发&#xff08;一&#xff09;&#xff1a;从看懂wav开始https://blog.csdn.net/Hellomino_/article/details/140873133?fromshareblogdetail&sharetypeblogdetail&sharerId140873133&sharereferPC&sharesourceHellomino_&…...

误差与误差限

目录 误差误差限小结 误差 设 x x x为准确值 , x ∗ ,x^* ,x∗为 x x x的一个近似值&#xff0c;称 e ∗ x ∗ − x e^*x^*-x e∗x∗−x为近似值的绝对误差&#xff0c;简称误差. 这样定义的误差 e ∗ e^{*} e∗可正可负&#xff0c;当绝对误差为正时近似值偏大&#xff0c;…...

halcon三维点云数据处理(七)find_shape_model_3d_recompute_score

目录 一、find_shape_model_3d_recompute_score例程代码二、set_object_model_3d_attrib_mod函数三、prepare_object_model_3d 函数四、create_cube_shape_model_3d函数五、获得CamPose六、project_cube_image函数七、find_shape_model_3d函数八、project_shape_model_3d函数 一…...

如何从串 ‘ 中国 +86‘ 中,获取到‘中国’:strip()、split()及正则表达式的使用

业务中有这样一个场景&#xff0c;国家列表中的数据格式是这样&#xff1a; 中国 86 &#xff0c;其中的 "中国" 前面有3个空格&#xff0c;需要从中提取出 "中国"&#xff0c;有哪些方法呢&#xff1f; 方法 1&#xff1a;使用 strip() 和 split() str…...

Java Web开发进阶——Spring Security基础与应用

Spring Security是Spring框架的核心模块之一&#xff0c;用于保护Web应用程序和微服务的安全。它提供强大的认证和授权功能&#xff0c;并与Spring生态系统无缝集成。本节将详细介绍Spring Security的基础知识及其在实际项目中的应用。 1. Spring Security概述与功能 1.1 什么…...

1. Doris分布式环境搭建

一. 环境准备 本次测试集群采用3台机器hadoop1、hadoop2、hadoop3, Frontend和Backend部署在同一台机器上&#xff0c;Frontend部署3台组成高可用&#xff0c;Backend部署3个节点&#xff0c;组成3副本存储。 主机IP操作系统FrontendBackendhadoop1192.168.47.128Centos7Foll…...

消息中间件类型介绍

消息中间件是一种在分布式系统中用于实现消息传递的软件架构模式。它能够在不同的系统或应用之间异步地传输数据&#xff0c;实现系统的解耦、提高系统的可扩展性和可靠性。以下是几种常见的消息中间件类型及其介绍&#xff1a; 1.RabbitMQ 特点&#xff1a; • 基于AMQP&#…...

Win10微调大语言模型ChatGLM2-6B

在《Win10本地部署大语言模型ChatGLM2-6B-CSDN博客》基础上进行&#xff0c;官方文档在这里&#xff0c;参考了这篇文章 首先确保ChatGLM2-6B下的有ptuning AdvertiseGen下载地址1&#xff0c;地址2&#xff0c;文件中数据留几行 模型文件下载地址 &#xff08;注意&#xff1…...

C# GID+绘制不透明和半透明的线条

绘制线条时&#xff0c;必须将 Pen 对象传递给 DrawLine 类的 Graphics 方法。 Pen 构造函数的参数之一是 Color 对象。 若要绘制不透明的线条&#xff0c;请将颜色的 alpha 分量设置为 255。 若要绘制半透明的线条&#xff0c;请将 alpha 分量设置为从 1 到 254 的任何值。 在…...

解锁 C# 与 LiteDB 嵌入式 NoSQL 数据库

一、开篇&#xff1a;邂逅 C# 与 LiteDB 新世界 在当今的软件开发领域&#xff0c;数据管理如同建筑的基石&#xff0c;而选择一款合适的数据库则是项目成功与否的关键因素之一。对于 C# 开发者来说&#xff0c;面对琳琅满目的数据库选项&#xff0c;如何抉择常常令人头疼。今…...

iOS - 数组的真实类型

1. NSArray 类簇 // 1. __NSArray0 (空数组) NSArray *empty [];// 2. __NSArrayI (不可变数组) NSArray *immutable [1, 2, 3];// 3. __NSArrayM (可变数组) NSMutableArray *mutable [NSMutableArray array];// 4. __NSSingleObjectArrayI (单元素数组) NSArray *single …...

Unity热更新 之 Addressables(2) 本地/远端打包 流程测试

基础篇&#xff1a;Unity热更新 之 Addressables(1) 资源基础加载-CSDN博客 基础方法来源于唐老狮,我也是初学热更这一块&#xff0c;所有不保证步骤完全正确&#xff0c;如有不足还请斧正 目录 0.前提 1.本地打包 1.1.资源放入包 1.2.简化路径名称给出标签(如有需要的话) …...

Python标准库之SQLite3

包含了连接数据库、处理数据、控制数据、自定义输出格式及处理异常的各种方法。 官方文档&#xff1a;sqlite3 --- SQLite 数据库的 DB-API 2.0 接口 — Python 3.13.1 文档 官方文档SQLite对应版本&#xff1a;3.13.1 SQLite主页&#xff1a;SQLite Home Page SQL语法教程&a…...

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…...

Linux第二课:LinuxC高级 学习记录day01

0、大纲 0.1、Linux 软件安装&#xff0c;用户管理&#xff0c;进程管理&#xff0c;shell 命令&#xff0c;硬链接和软连接&#xff0c;解压和压缩&#xff0c;功能性语句&#xff0c;结构性语句&#xff0c;分文件&#xff0c;make工具&#xff0c;shell脚本 0.2、C高级 …...

Notepad++上NppFTP插件的安装和使用教程

一、NppFTP插件下载 图示是已经安装好了插件。 在搜索框里面搜NppFTP&#xff0c;一般情况下&#xff0c;自带的下载地址容易下载失败。这里准备了一个下载连接&#xff1a;Release v0.29.10 ashkulz/NppFTP GitHub 这里我下载的是x86版本 下载好后在nodepad的插件里面选择打…...

怎样提高服务器中的数据传输速度?

服务器中的数据传输速度会影响着用户的体验感&#xff0c;当企业中的数据传输速度出现卡顿或者是过慢时&#xff0c;用户不能及时浏览到所需的内容&#xff0c;给用户造成不好的体验感&#xff0c;那么企业该怎样才能提高服务器中的数据传输速度呢&#xff1f; 服务器之间如何传…...

Java聊天小程序

拟设计一个基于 Java 技术的局域网在线聊天系统,实现客户端与服务器之间的实时通信。系统分为客户端和服务器端两类,客户端用于发送和接收消息,服务器端负责接收客户端请求并处理消息。客户端通过图形界面提供用户友好的操作界面,服务器端监听多个客户端的连接并管理消息通…...

Spring事件发布与监听

Spring事件机制详解&#xff1a;事件发布与监听 在Spring框架中&#xff0c;事件机制基于发布-订阅模式&#xff0c;允许组件之间进行解耦。发布者发布事件&#xff0c;监听者订阅并响应这些事件。Spring事件机制的核心在于ApplicationEvent和ApplicationListener&#xff0c;…...

【PPTist】公式编辑、插入音视频、添加动画

一、插入公式 点击公式的时候 latexEditorVisible 会变成 true src/views/Editor/CanvasTool/index.vue <Modalv-model:visible"latexEditorVisible" :width"880" ><LaTeXEditor close"latexEditorVisible false"update"data &…...

Dart语言的面向对象编程

Dart语言的面向对象编程 Dart是一种由谷歌开发的编程语言&#xff0c;主要用于构建Web、移动应用及服务器端应用。作为一门现代编程语言&#xff0c;Dart自带丰富的特性&#xff0c;尤其是在面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;方面&#x…...

selenium+pyqt5自动化工具总结

说明&#xff1a;本工具是&#xff0c;操作外部google浏览器、selenium是无法操作qt界面中嵌套的浏览器的&#xff0c; 工具在后面 1. 代码结构 pycharm打开的文件下&#xff0c;再写一个子文件&#xff0c;文件导入的时候把子文件名带上 这样就可以在 外层使用命令 pyinst…...

Java 基于微信小程序的高校科研团队管理系统设计与实现(附源码,部署,文档

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

如何规模化实现完全自动驾驶?Mobileye提出解题“新”思路

在CES 2025上&#xff0c;Mobileye展示了端到端自动驾驶系统Mobileye Drive™&#xff0c;通过高度集成的传感器、算法和计算平台&#xff0c;可以实现自动驾驶功能的全覆盖。 Mobileye创始人兼首席执行官Amnon Shashua教授 期间&#xff0c;Mobileye创始人兼首席执行官Amnon …...

Vue2与Vue3在项目开发中的选择:深入探讨

文章目录 前言一、Vue2的优势与挑战二、Vue3的进步与特性三、如何做出选择&#xff1f;结语 前言 Vue.js 是一个用于构建用户界面的渐进式JavaScript框架。Vue2和Vue3是其两个主要版本&#xff0c;它们各自拥有一系列特点和优势。随着Vue3的发布&#xff0c;开发者们面临着在新…...

Git 操作与技巧

一、开发日常常用 Git 操作与技巧 1.1 基础操作 1.1.1 查看 Git 状态 git status&#xff1a;查看当前工作区的状态&#xff0c;了解哪些文件已经修改、哪些文件已经暂存。git status这个命令是最常用的命令之一&#xff0c;可以帮助你理解当前的开发状态&#xff0c;哪些文…...

vs2022开发.net窗体应用开发环境安装配置以及程序发布详细教程

文章目录 一、安装visual studio1.1推荐win10操作系统1.2推荐vs20221.3选择工作负载 二、新建基于.net的winform应用程序2.1为什么要.net 2.2 新建.net窗体应用2.2.1 选择Window窗体应用2.2.2 .net窗体对比framework窗体 三、发布.net应用 一、安装visual studio 1.1推荐win10…...

Mysql--基础篇--视图,存储过程,触发器

1、视图 MySQL视图&#xff08;View&#xff09;是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。但是&#xff0c;视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表&#…...

代码随想录 哈希 test 8

18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 与三数之和类似&#xff0c;重点在剪枝和去重的区别&#xff0c;由于target可正可负&#xff0c;因此需要分两种情况讨论&#xff0c;如果target为正&#xff0c;则若当前选择的元素之和大于target&#xff0c;需要跳出这…...

Postman接口测试基本操作

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Postman-获取验证码 需求&#xff1a;使用Postman访问验证码接口&#xff0c;并查看响应结果。 地址&#xff1a;http://kdtx-test.itheima.net/api/captchaIm…...

Three.js 渲染技术:打造逼真3D体验的幕后功臣

文章目录 前言一、着色器&#xff08;Shaders&#xff09;二、后处理&#xff08;Post-processing&#xff09;三、抗锯齿&#xff08;Anti-aliasing&#xff09;四、实时渲染与离线渲染五、光照模型与材质优化六、环境映射&#xff08;Environment Mapping&#xff09;七、纹理…...

uml活动图和用例图之间有一致性要求吗

UML&#xff08;统一建模语言&#xff09;中的活动图和用例图是两种不同的图表&#xff0c;它们用于描述软件系统的不同方面。尽管它们有不同的用途&#xff0c;但它们之间存在一定的一致性要求&#xff0c;以保证模型的有效性和准确性。 以下是活动图和用例图之间一致性要求的…...

嵌入式入门Day38

C Day1 第一个C程序C中的输入输出输出操作coutcin练习 命名空间使用方法自定义命名空间冲突问题 C对字符串的扩充C风格字符串的使用定义以及初始化C风格字符串与C风格字符串的转换C风格的字符串的关系运算常用的成员变量输入方法 布尔类型C对堆区空间使用的扩充作业 第一个C程序…...

什么叫区块链?怎么保证区块链的安全性?

区块链&#xff08;Blockchain&#xff09;是一种分布式数据库或账本技术&#xff0c;它通过去中心化的方式记录交易或其他数据&#xff0c;并确保这些记录是安全、透明和不可篡改的。区块链最初是作为比特币&#xff08;Bitcoin&#xff09;加密货币的基础技术而被公众所知&am…...

探秘block原理

01 概述 在iOS开发中&#xff0c;block大家用的都很熟悉了&#xff0c;是iOS开发中闭包的一种实现方式&#xff0c;可以对一段代码逻辑进行封装&#xff0c;使其可以像数据一样被传递、存储、调用&#xff0c;并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…...

Unity2D初级背包设计后篇 拓展举例与不足分析

Unity2D初级背包设计中篇 MVC分层撰写(万字详解)-CSDN博客、 如果你已经搞懂了中篇&#xff0c;那么对这个背包的拓展将极为简单&#xff0c;我就在这里举个例子吧 目录 1.添加物品描述信息 2.拓展思路与不足分析 1.没有删除只有丢弃功能&#xff0c;所以可以添加垃圾桶 2.格…...

云计算基础,虚拟化原理

文章目录 一、虚拟化1.1 什么是虚拟化1.2 虚拟化类型 二 、存储虚拟化2.1 存储指标2.2 存储类型2.3 存储协议2.4 RAID 三、内存 i/O虚拟化3.1 内存虚拟化基本概念地址空间转换原理内存共享与隔离原理 3.2 I/O 虚拟化基本概念模拟&#xff08;Emulation&#xff09;方式半虚拟化…...

Android13工具修改wifi mac地址以后没有更新的问题

Android13系统在通过烧写工具更新修改wifi mac地址以后&#xff0c;在系统设置里面查看wifi mac地址还是之前的&#xff0c;没有更新。 原因&#xff1a;android13 系统中packages\modules\Wifi\service\ServiceWifiResources\res\values\config.xml新增了"config_wifiSav…...