【新书推荐】8.1 数组

news2024/9/29 11:36:09

第八章 数组

数组是程序设计中最常用的数据类型之一。数组表示在指定的内存地址处,连续存储具有相同数据类型的一组元素。每个数组元素可以视为一个单独的变量,使用数组名和数组下标来表示。例如int类型的数组元素a[2],表示在内存地址a处,存储从0开始计数的第2个数组元素。数组元素可以看作是一组单个变量定义的简化形式。

本章学习概要:

  数组的概念

  数组遍历访问

  多维数组

8.1 数组

本节必须掌握的知识点:

        数组的概念

        示例二十九

        代码分析

        汇编解析

8.1.1 数组的概念

什么是数组?数组是一个变量;由数据类型相同的一组元素组成,并且连续地存储在内存中。

【注:数组里的元素一定具有相同的数据类型】

那么数组既然是一个变量,它和其它基本变量有什么不同呢?基本变量在内存中是一块空间,比如定义一个int型变量,那么它在内存中存在的大小空间是4字节。而数组就不同了,数组是一串连续的内存空间。在下面示例中我们将详细介绍到。

数组的语法格式

数组的语法格式:

数据类型 名称[];

●解析:

我们已经了解了 char、short、int、float、double、const等数据类型,这些都可以组成不同类型的数组。名称就是变量名,中括号”[]”内写的数值大小代表数组的元素个数。

【注:”[]”数组元素个数在中括号内指定,且中括号内必须是整型常量】

数组的命名

既然数组是变量,那么它的命名规则和基本变量相同,即“数字、字母、下划线的组合,但不能以数字开头”。

【注】编译器编译时,数字开头表示行号。

举例

char c[50]; 定义了一个char型数组,数组的元素个数为50;

short s[24]; 定义了一个short型数组,数组的元素个数为24;

int i[24]; 定义了一个int型数组,数组的元素个数为24;

int  arr[50]; 数组名arr表示数组的起时地址。

int  _arr[50]; 数组名_arr表示数组的起时地址。

8.1.2 示例二十九

数组的用途

数组有什么作用哪?我们来看一个例子。

●第一步:分析需求,设计程序结构框架。

分析需求:依次输入5名同学的分数,并显示他们的平均分及总分。

设计程序结构框架:顺序结构,依次输入5名同学的分数,然后计算他们的总分和平均分。

●第二步:数据定义,定义恰当的数据结构;

定义5个int类型的变量a,b,c,d,e,分别代表5名同学。再定义一个int类型变量sum保存总分,并初始化为0;定义一个double类型变量ave保存平均分,并初始化为0。

●第三步:分析算法。

sum = a + b + c + d + e;

ave = sum / 5.0;

●第四步:编写伪代码,即用我们自己的语言来编写程序。

int main(void) {

定义int类型变量a,b,c,d,e,并初始化为0,分别代表5名同学;

定义int类型变量sum,并初始化为0,保存总分;

定义double类型变量ave,并初始化为0,保存平均分;

调用printf函数打印信息("请输入5名同学的分数。\n");

调用printf函数打印信息("a:");

调用scanf_s接收键盘输入变量a;

调用printf函数打印信息("b:");

调用scanf_s接收键盘输入变量b

调用printf函数打印信息("c:");

调用scanf_s接收键盘输入变量c

调用printf函数打印信息("d:");

调用scanf_s接收键盘输入变量d

调用printf函数打印信息("e:");

调用scanf_s接收键盘输入变量e

计算总分:sum = a + b + c + d + e;

计算平均分:ave = sum / 5.0;

调用printf函数输出结果:

("5名同学的总分为: %d\t平均分为: %.1f \n", sum, ave);

system("pause");

return 0;    

}

●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图;(略)

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   依次输入5名同学的分数,并显示他们的平均分及总分

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

int a = 0;      //a同学的分数;

int b = 0;      //b同学的分数;

int c = 0;      //c同学的分数;

int d = 0;      //d同学的分数;

int e = 0;      //e同学的分数;

double ave = 0;     //平均分;

int sum = 0;    //总分;

printf("请输入5名同学的分数。\n");

printf("a:");

scanf_s("%d", &a);

printf("b:");

scanf_s("%d", &b);

printf("c:");

scanf_s("%d", &c);

printf("d:");

scanf_s("%d", &d);

printf("e:");

scanf_s("%d", &e);

sum = a + b + c + d + e;

ave = sum / 5.0;

printf("5名同学的总分为: %d\t平均分为: %.1f \n", sum, ave);

system("pause");

return 0;

}

输出结果:

请输入5名同学的分数。

a:99

b:88

c:77

d:66

e:55

5名同学的总分为: 385    平均分为: 77.0

请按任意键继续. . .

●第七步:调试程序,修复程序中可能出现的BUG;

(略)

●第八步:优化代码,尝试更好的设计方案,效率更高的算法,逻辑更为清晰简洁明了。

示例代码二十九看似解决了这个问题,但是假如要输出100名同学的成绩,那我们该如何解决呢?难道还用示例代码二十九所展示的那样创建100个变量名?那未免太累了吧。我们不防使用数组来解决这个棘手的问题,请看实验五十五。

实验五十五: 一维数组

在VS中新建项目8-1-2.c:

/*

   依次输入5名同学的分数,并显示他们的平均分及总分

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

int score[5];     //5名同学的成绩

int sum = 0;      //总分

double ave = 0;   //平均分

printf("请输入5名同学的成绩。\n");

for (int i = 0; i < 5; ++i)

{

printf("请输入第%d名同学分数:", i+1);

scanf_s("%d", &score[i]);

sum += score[i];

}

ave = sum / 5.0;

printf("5名同学的总分为:%d\t 平均分为 %.1f\n", sum, ave);

system("pause");

return 0;

}

输出结果:

请输入5名同学的成绩。

请输入第1名同学分数:1

请输入第2名同学分数:2

请输入第3名同学分数:3

请输入第4名同学分数:4

请输入第5名同学分数:5

5名同学的总分为:15      平均分为 3.0

请按任意键继续. . .

8.1.3 代码分析

示例二十九中代表5名同学的变量定义改用数组的方式定义:

int score[5];//score地址处分配5个int类型的地址空间,用于保存5名同学的成绩

然后再分别定义一个int类型变量sum,且初始化为0,用于保存总分;定义一个double类型的变量ave,且初始化为0,用于保存平均分。

接下来使用for循环语句 (int i = 0; i < 5; ++i),循环变量i的取值分别为0,1,2,3,4。循环5次,提示接收用户键盘输入5名同学的分数,并保存在数组元素score[0]score[1]score[2]score[3]score[4]内,完成数组初始化。

提示

int score[5]的含义:在score地址处分配5个int类型的地址空间。

&score[i]的含义为:score+i*sizeof(int)偏移地址,即第i个数组元素的地址。

score[i]的含义为:score+i*sizeof(int)偏移地址存储的值,即第i个数组元素的值。

int score[5];表示数组的元素个数为5,它是从下标0开始访问的。“[]”中括号中的操作数称为下标。比如score[3],其下标为3,表示score[3]是数组的第3个元素。

也就是说int score[5];可以写成 score[0]、score[1]、score[2]、score[3]、score[4]共5个元素。

for(i=0;i<5;i++) //for循环遍历数组,什么叫遍历数组?就是循环访问数组中每个元素。

{

printf("分数为:%d\n",score[i]); //输出数组元素的值

sum += score[i];  // 相当于sum = score[i]+sum。     

}

在完成数组初始化之后,sum += score[i];语句使用复合运算符“+=” 计算总分。for循环结束后,使用ave = sum / 5.0;语句计算平均分。

最后使用printf函数输出总分和平均分。

8.1.4 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

score sdword  5 dup(?)

sum sdword  0

ave real8  0.0

i sdword  0

divisor dword  5 ;除数

.const

szMsg1 db "请输入5名同学的成绩。",0dh,0ah,0

szMsg2 db "请输入第%d名同学分数:",0

szMsg3 db "%d",0

szMsg4 db "5名同学的总分为:%d",09h,"平均分为 %.1f",0dh,0ah,0

.code

start:

invoke printf,offset szMsg1

.while i < 5

mov ecx,i

inc ecx

invoke printf,offset szMsg2,ecx

mov ebx,i

; ;数组元素的地址score+4*i

shl ebx,2

lea ecx,score

add ecx,ebx

invoke scanf,offset szMsg3,ecx

mov eax,sum

;4*i

mov ebx,i

shl ebx,2

add eax,sdword ptr [score+ebx] ;取数组元素值[score+4*i]

mov sum,eax

inc sdword ptr i

.endw

;浮点运算ave = sum / 5.0;

fild divisor ;加载浮点栈

fild sum ;加载浮点栈

fdiv ;浮点除法指令

fst ave ;保存结果

invoke printf,offset szMsg4,sum,ave

;

invoke _getch

ret

end start

●输出结果:

请输入5名同学的成绩。

请输入第1名同学分数:1

请输入第2名同学分数:2

请输入第3名同学分数:3

请输入第4名同学分数:4

请输入第5名同学分数:5

5名同学的总分为:15     平均分为 0.3

上述汇编代码中,使用.while伪指令对应C语言中的for循环语句。此外,我们需要特别关注以下几点:

1.数组定义为:score sdword  5 dup(?),意思是在score地址处分配5个sdword类型的未初始化内存空间。

2.取数组元素的地址:地址表达式score+4*i计算第i个数组元素在内存中的偏移地址。score表示数组的起始地址,即第0个数组元素的地址。4为比例因子,表示每个数组元素的数据类型sdword占用4个字节的内存空间。变量i为数组元素的下标,使用数组下标*比例因子=数组元素的地址。

3.取数组元素的值[score+4*i] :方括号表示内存空间存储的值,方括号内为数组元素的地址。

4.浮点数的计算:(参见《X86汇编语言基础教程》第三十九章 浮点处理器和浮点指令编码)

fild divisor 表示将除数转换为浮点数,然后加载到浮点栈,浮点栈由8个80位浮点寄存器组成。

fild sum表示将和转换为浮点数,然后加载到浮点栈。

fdiv ;浮点除法指令,计算sum/5.0.

fst ave ;将浮点栈顶的值存储到变量ave中

5.我们会发现最后输出的结果是错误的。因为保存在变量ave中的浮点数为64位,而printf输出的浮点数的格式与变量ave存储的格式不同。如果在汇编语言中正确的输出浮点数,需要对浮点数的格式进行转换,请读者参考源代码中的floatio.asm源文件中的WriteFloat函数定义。

 

总结

C语言中的使用数组下标表示相应的数组元素时,隐含了比例因子。汇编语言中精确的计算数组元素的偏移地址(以字节为单位)。

C语言标准库中的输入和输出函数实现了数据的格式化输出,而汇编语言中需要自己实现数据格式的转换。

C语言中会严格检查数组占用的内存空间是否发生溢出,而汇编语言中不做相应的检查,即使出现错误,也不会报错。这相应提高了对程序员的要求。由于我们在《X86汇编语言基础教程》做过类似的实验,此处不再赘述,请读者自己编写汇编代码验证一下。

反汇编代码

int score[5];     //5名同学的成绩

int sum = 0;      //总分

01201090  mov         dword ptr [sum],0  ;变量sum初始化为0

double ave = 0;   //平均分

01201097  xorps       xmm0,xmm0  

0120109A  movsd       mmword ptr [ave],xmm0  ;变量ave初始化为0

printf("请输入5名同学的成绩。\n"); ;输出提示信息

0120109F  push        1203000h  

012010A4  call        printf (01201150h)  

012010A9  add         esp,4  

for (int i = 0; i < 5; ++i)

012010AC  mov         dword ptr [ebp-1Ch],0  ;表达式1:初始化循环变量i为0

012010B3  jmp         main+3Eh (012010BEh)  

012010B5  mov         eax,dword ptr [ebp-1Ch]  ;表达式3,i++

012010B8  add         eax,1  

012010BB  mov         dword ptr [ebp-1Ch],eax  

012010BE  cmp         dword ptr [ebp-1Ch],5  ;表达式2

012010C2  jge         main+7Ch (012010FCh)   ;变量i>=5时跳转012010FCh地址处

{

printf("请输入第%d名同学分数:", i+1);

012010C4  mov         ecx,dword ptr [ebp-1Ch]  

012010C7  add         ecx,1  

012010CA  push        ecx  

012010CB  push        1203018h  

012010D0  call        printf (01201150h)  ;输出提示信息

012010D5  add         esp,8  

scanf_s("%d", &score[i]);接收键盘输入,并存入数组

012010D8  mov         edx,dword ptr [ebp-1Ch]  ;取出循环变量i的值存入edx

012010DB  lea         eax,score[edx*4]  ;将第i个数组元素的地址存入eax

012010DF  push        eax  

012010E0  push        1203030h  

012010E5  call        scanf_s (01201190h)  ;将键盘输入的值存入第i个数组元素地址处

012010EA  add         esp,8  

sum += score[i];

012010ED  mov         ecx,dword ptr [ebp-1Ch]  ;将循环变量i存入ecx

012010F0  mov         edx,dword ptr [sum]   ;将变量sum的值存入edx

012010F3  add         edx,dword ptr score[ecx*4]  ;将第i个数组元素的值累加到edx

012010F7  mov         dword ptr [sum],edx  ;将累加和存入变量sum

}

012010FA  jmp         main+35h (012010B5h)  ;跳转到表达式3

ave = sum / 5.0;浮点运算,计算平均分

012010FC  cvtsi2sd    xmm0,dword ptr [sum]  

ave = sum / 5.0;

01201101  divsd       xmm0,mmword ptr [__real@4014000000000000 (01202100h)]  

01201109  movsd       mmword ptr [ave],xmm0  

printf("5名同学的总分为:%d\t 平均分为 %.1f\n", sum, ave);

0120110E  sub         esp,8  

01201111  movsd       xmm0,mmword ptr [ave]  

01201116  movsd       mmword ptr [esp],xmm0  

0120111B  mov         eax,dword ptr [sum]  

0120111E  push        eax  

0120111F  push        1203034h  

01201124  call        printf (01201150h)  ;输出总分和平均分

01201129  add         esp,10h  

system("pause");

0120112C  push        1203058h  

01201131  call        dword ptr [__imp__system (01202060h)]  

01201137  add         esp,4  

return 0;

上述反汇编代码中,我们可以清晰的看出,数组名就是数组在内存中的起始地址。数组元素的下标*数组数据类型对应的比例因子得到准确的数组元素地址。读写数组元素首先是计算出每个数组元素的偏移地址,然后再对其进行读写操作。

请读者仔细阅读代码注释,理解程序的执行流程。

实验五十六: 测试数组越界导致的内存溢出错误

在VS中新建项目8-1-3.c:

/*

   数组溢出

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

int score[5];     //5名同学的成绩

int sum = 0;      //总分

double ave = 0;   //平均分

printf("请输入5名同学的成绩。\n");

for (int i = 0; i < 5; ++i)

{

printf("请输入第%d名同学分数:", i + 1);

scanf_s("%d", &score[i]);

sum += score[i];

}

score[5] = 10;//数组下标5超出范围

ave = sum / 5.0;

printf("5名同学的总分为:%d\t 平均分为 %.1f\n", sum, ave);

system("pause");

return 0;

}

在C语言中,i表示数组元素的下标。假设数组定义为int a[i];数组下标i的取值范围为0~n-1。如果下标超出范围,则会导致数组溢出,在C语言中可以正常通过编译,但是程序执行时,会导致内存溢出错误。例如,在8-1-2.c代码中添加下面的语句:

score[5] = 10;//数组下标5超出范围

编译后运行,显示如下错误提示:

                图8-1 内存溢出错误

实验五十七: 观察内存中的数组存储

第一步:在项目8-1-2.c的int sum = 0; //总分语句处下一个断点,并打开watch窗口、内存窗口。

第二步:在监视1窗口名称栏输入数组名score,获取score地址及处存储的值。如图8-2所示。【注】数组名本身就是数组的起始地址,无需添加‘&‘地址符。

                                图8-2 查询数组地址及存储的值

第三步:将数组score的地址输出内存窗口的地址栏并回车,如图8-3所示。

                                图8-3 查看数组内存存储

如上图所示,在数组score未初始化之前,其内存存储的值是之前内存中遗留下来的数据。

第四步:按F10单步执行,接收键盘输入5个数组元素的值,并存入数组。如图8-4所示。

                                图8-4 数组的初始化

由上同可知,从键盘输入了1,2,3,4,5五个整数值,并已存入数组内。5个数组元素的地址分别为:

score[0]对应的内存地址是0x00F3FB70;

score[1]对应的内存地址是0x00F3FB74;

score[2]对应的内存地址是0x00F3FB78;

score[3]对应的内存地址是0x00F3FB7C;

score[4]对应的内存地址是0x00F3FB80;

由于我们定义的数组是int类型的,所以一个int占4个字节,5个int占20个字节,且这20个字节都是连续的,如图8-4所示。同理可知,如果是short类型数组,那么每个元素就占2字节;char类型数组,那么每个元素就占1字节。

数组的初始化

数组初始化有以下几种形式:

  1. 可以在定义数组的时候,指定每一个元素的初始值:

int arr[3]={1,2,3};

2.定义数组时全部初始值为0:

       int arr[3] = {0};    // 相当于arr[3] = {0,0,0};

3.定义数组时可以不赋初始值:

   int arr[3];

4.指定一部分初始值:

   int arr[5]={1,2,3};  //只指定前三个元素的初始值arr[5] = {1,2,3,0,0};

5.int arr[] = {1,2,3,4}; //当我们没有对数组定义元素个数时,必须有初始值。如arr数组里共有4个元素,那么编译器会自动默认为4个元素,也就是数组长度是4。

●错误写法:

1.int arr[3] = {1,2,3,4}; //这种写法是越界的行为,什么是越界?当初始值的个数超过数组元素个数的时候,程序会发生错误。

2.int arr[3];

arr = {1,2,3}; //不能使用赋值语句进行初始化,因为数组名表示地址,而不是变量

获取数组大小

数组的大小由元素的类型和元素的个数共同决定的。

可以使用sizeof获取数组大小:

int arr[100];

int size = sizeof(arr);

实验五十八: 获取数组的大小

在VS中新建项目8-1-4.c:

/*

   获取数组的大小

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

int arr[100];

int size = sizeof(arr);

printf("arr数组的大小为%d\n",size);

system("pause");

return 0;

} 

●输出结果:

arr数组的大小为400

请按任意键继续. . .

●解析:

int 是4字节,定义了元素个数为100,所以长度为100*4字节=400字节。

练习

1、以下定义的数组哪些是错误的,为什么?

(1)、int arr [10] = {1,2,,3,4};

(2)、char char [];

(3)、short arr1 [10] = {};

(3)、int arr1 [] = {0};

2、请分别写出下面定义数组的元素的个数及数组长度。

(1)、short arr [10] = {1,2,3,3,4};

(2)、char char []={1,2,3,3,4};

(3)、int arr1 [13] = {0

3、使用do while语句和while语句重写8-1-2.c。

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

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

相关文章

input输入框过滤非金额内容保留一个小数点和2位小数

这篇是输入框过滤非金额内容保留一个小数点和2位小数&#xff0c;金额的其他格式化可以看这篇文章常用的金额数字的格式化方法 js方法直接使用 该方式可以直接使用过滤内容&#xff0c;也可以到onInput或onblur等地方过滤&#xff0c;自行使用 /*** 非金额字符格式化处理* p…

Java数据结构---初识集合框架

目录 一、什么是集合框架 二、集合框架的重要性 三、背后涉及的数据结构及算法 1.什么是数据结构 2.容器背后对应的数据结构 3.相关的Java知识 4.什么是算法 一、什么是集合框架 Java 集合框架 Java Collection Framework &#xff0c;又被称为容器 container &#xff0…

深度学习基础(三)循环神经网络(RNN)

之前的章节我们初步介绍了卷积神经网络&#xff08;CNN&#xff09;&#xff1a; 深度学习基础&#xff08;二&#xff09;卷积神经网络&#xff08;CNN&#xff09;-CSDN博客文章浏览阅读2次。卷积神经网络&#xff08;CNN&#xff09;的应用领域广泛&#xff0c;尤其在图像处…

设计模式(八)外观模式

相关文章设计模式系列 1.外观模式简介 外观模式介绍 当我们开发Android的时候&#xff0c;无论是做SDK还是封装API&#xff0c;我们大多都会用到外观模式&#xff0c;它通过一个外观类使得整个系统的结构只有一个统一的高层接口&#xff0c;这样能降低用户的使用成本。 外观…

片上网络NoC

本文大部分内容来源于王志英老师主编的《片上网络原理与设计》以及网络&#xff0c;部分内容是本人理解所得&#xff0c;若有不当之处请指教 一、概述 片上网络将报文交换的思想引入芯片内部通信机制中&#xff0c;尽管片上网络和片外网络具有一定相似性&#xff0c;但二者在…

Vue 实现页面导出A4标准大小的PDF文件,以及处理图片跨域不能正常展示的问题等

效果预览&#xff1a; 代码流程&#xff1a;首先在utils文件夹下创建htmlToPdf的js工具文件&#xff0c;然后在main.js中注册引用 htmlToPdf.js // 导出页面为PDF格式 import html2Canvas from html2canvas import JsPDF from jspdfexport default {install(Vue, options) {V…

el-table样式问题:如何修改element-ui表格中按钮悬浮显示但是被el-table溢出隐藏的问题?

最近在写elment-ui样式表格中遇到了溢出隐藏的问题 修改前 修改后 是由于el-table__body-wrapper为 overflow&#xff1a;hidden导致的 解决方式&#xff1a; .el-table__body-wrapper {overflow: visible !important; } //或者 /deep/.el-table__body-wrapper {overflow: v…

更换个人开发环境后,pycharm连接服务器报错Authentication failed

原因&#xff1a;服务器中更换个人开发环境后&#xff0c;密码变了。 解决&#xff1a;在pycharm中修改服务器开发环境密码即可。 1 找到Tools-Depolyment-Configuration 2 点击SSH Configuration后的省略号 3 修改这里面的Password即可

刷题日记 | 字符串扩容和增强型for循环

for(char c:s)遍历字符串 增强型for循环 C for(char c:s)遍历字符串 增强型for循环_c for (char c : s)-CSDN博客 字符串使用前要进行扩容 reserve函数 【CString类成员函数辨析】resize(),size(),capacity(),reserve()函数的解析与对比_c reserve函数-CSDN博客 a.size() 用来…

鲲鹏arm64架构下安装KubeSphere

鲲鹏arm64架构下安装KubeSphere 官方参考文档: https://kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/ 在Kubernetes基础上最小化安装 KubeSphere 前提条件 官方参考文档: https://kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequi…

SIMON 32/64加密电路的实现(System Verilog)

关于SIMON加密电路的原理&#xff0c;参考之前发布的博文【SIMON加密算法的原理】 1.总览与电路介绍 1.1 电路总体结构图 1.2 模式配置介绍 SIMON加密算法的分组长度、密钥长度以及必要的参数配置如下图&#xff1a; 本次需要实现的是SIMON 32/64&#xff0c;即分组长度2n3…

【LeetCode每日一题】938. 二叉搜索树的范围和

2024-2-26 文章目录 [938. 二叉搜索树的范围和](https://leetcode.cn/problems/range-sum-of-bst/)思路&#xff1a;写法一&#xff1a;在中间累加写法二&#xff1a;在最后累加 938. 二叉搜索树的范围和 思路&#xff1a; 1.在二叉搜索树中&#xff1a;左子树的结点都小于根节…

LeetCode69. x 的平方根(C++)

LeetCode69. x 的平方根 题目链接代码 题目链接 https://leetcode.cn/problems/sqrtx/description/ 代码 class Solution { public:int mySqrt(int x) {int right x, left 0, ans -1;while(left < right){long long mid left (right - left) / 2;if(mid * mid <…

System V版本的共享内存

在之前的学习中我们学习到了使用匿名和命名管道进行进程间的通信&#xff0c;下面我们再来使用一种新的方式进行进程间的通信。 我们下面要学习的是system V版本的共享内存。 首先我们要知道什么是system V 首先我们要知道我们在之前学习的管道通信的代码并不是一个专门设计…

1995-2021年全国30省能源消费总量(万吨标煤)

1995-2021年全国30省能源消费总量&#xff08;万吨标煤&#xff09; 1、时间&#xff1a;1995-2021年 2、范围&#xff1a;30省市不含西藏 3、来源&#xff1a;能源统计年鉴 各省年鉴 3、指标: 能源消费总量 4、单位&#xff1a;万吨标煤 5、缺失情况&#xff1a;新疆202…

贝叶斯核机器回归拓展R包:bkmrhat

1.摘要 bkmrhat包是用于扩展bkmr包的贝叶斯核机器回归&#xff08;Bayesian Kernel Machine Regression, BKMR&#xff09;分析工具&#xff0c;支持多链推断和诊断。该包利用future, rstan, 和coda包的功能&#xff0c;提供了在贝叶斯半参数广义线性模型下进行identity链接和 …

C# 通过共享内存调用C++ 算法

需求&#xff1a; C#程序调用 C开发的dll. 一种C# 程序调用c 算法方案_算法怎么被c#调用-CSDN博客 上回书说到&#xff0c;将c算法封装为dll 插件&#xff0c;c加载后&#xff0c;暴露C风格接口&#xff0c;然后供C#调用。但是这样有几个问题&#xff1a; 1&#xff0c;一是…

Django后台管理(二)

一、自定义注册管理类介绍 官网:Django 管理站点 | Django 文档 | Django 注册模型除了使用 Django 默认的管理类admin,也可以自定义,比如: class StudentAdmin(admin.ModelAdmin):pass admin.site.register(Student, StudentAdmin)ModelAdmin 类是管理界面中模型的表示。…

Java四大引用详解:强引用、软引用、弱引用、虚引用

在JDK1.2以前的版本中&#xff0c;当一个对象不被任何变量引用&#xff0c;那么程序就无法再使用这个对象。也就是说&#xff0c;只有对象处于可触及状态&#xff0c;程序才能使用它。这就像在商店购买了某样物品后&#xff0c;如果有用就一直保留它&#xff0c;否则就把它扔到…

【深度学习】微调ChatGlm3-6b

1.前言 指令微调ChatGlm3-6b。微调教程在github地址中给出&#xff0c;微调环境是Qwen提供的docker镜像为环境。 镜像获取方式&#xff1a;docker pull qwenllm/qwen:cu117 github地址&#xff1a;https://github.com/liucongg/ChatGLM-Finetuning 2.微调过程 github地址中的教…