C语言系统化精讲(二):C语言数组详解

news2024/11/17 20:36:14

文章目录

  • 一、数组的基本概念
  • 二、一维数组
    • 2.1 一维数组的定义
    • 2.2 一维数组初始化
    • 2.3 一维数组的引用
  • 三、二维数组
    • 3.1 二维数组的定义
    • 3.2 二维数组初始化
    • 3.3 二维数组的引用
  • 四、C语言数组是静态的,不能插入或删除元素
  • 五、C语言数组的越界和溢出
    • 5.1 数组越界
    • 5.2 数组溢出

2018年9月1日,中国女排在2018年亚运会上3:0战胜了泰国女排,夺得了冠军,此时,阿里巴巴董事长主席马云见证了中国女排夺冠的辉煌一刻。同时马云承诺,要帮中国女排姑娘们清理购物车。本示例就来模拟列出某女孩的购物车清单,具体代码如下所示:
在这里插入图片描述
从代码中可以看到,图中被框出来的部分 长相类似 都是一个 标识符一个中括号([]) 箭头的另一端写着两个大字――数组,接下来我们简单的介绍一下数组的成分。

  1. DailyUse、Makeup、Sports、Health:即标识符。它们就是按照命名标识符规则定义的标识符,是程序员DIY定义的:
  2. []:即中括号。他的作用就是扩住数组的长度,中括号中间写的是数组的长度。
  3. 100、50、200、i等:即数组的长度。表示定义这个数组的长度。

根据上述,数组的形式就类似 a[10],没错,这是数组的形式之一,接下来我们详细介绍本章内容――数组,了解数组的作用,如何定义数组、初始化数组以及使用数组。

一、数组的基本概念

在某女孩的购物车清单实例中可以看到:

char DailyUse[50] = {"纸抽,纸巾,收纳箱,水杯,垃圾袋,剪刀,挂钩,拖鞋,小闹钟"};

这行代码中,DailyUse[50] 表示多个字符类型的变量,可以使用同一个名字 DailyUse,从而组成的集合,它就是一个数组。我们都知道,要想把数据放到内存中,就需要先分配内存,要想放入4个整型数据,就得分配4个int类型的内存空间,例如:

int arr[4];

这样我们就给分配了4个int型的内存空间,共计占4x4=16个字节,并为它们起了一个名字arr。我们把这样的一组数据的集合,叫做 数组(Array); 它所包含的每一个数据叫做 数组元素(Element); 所包含的数据的个数称为 数组长度(Length), 例如 int arr[4]; 就定义了一个长度为4的整型数组,名字是arr。数组中的每个元素都有一个序号,这个序号从 0 开始,而不是从我们熟悉的1开始,称为 下标(Index)。

二、一维数组

一维数组就像12个月,我们可以将12月起同一个名字month,1月~12月就是数组month的元素,示意图如下图所示:
在这里插入图片描述

2.1 一维数组的定义

一维数组是用于存储一维数组中数据的集合,它的一般形式如下:

类型说明符 数组标识符[常量表达式];
// ①: 类型说明符表示数组中的所有元素类型
// ②: 数组标识符表示该数组型变量的名称,命名规则与变量名一致
// ③: 常量表达式定义了数组中存放的数据元素的个数,即数组长度。例如cArray[10],10表示数组中有10个元素,下标从0开始,到9结束

示例:

//1.定义一个长度为10的字符型数组
//char为数组元素的类型,而cArray表示的是数组变量名,括号中的10表示的是数组中包含的元素个数
char cArray[10];
//2.定义一个长度为5的整型数组
int number[5];
//3.定义一个长度为20的浮点型数组
float f[20];

定义数组还有以下几点注意事项:

同一个数组,数组的所有元素的数据类型都是相同的
数组名的书写规则应按照标识符的规定定义
允许在同一个类型说明中,说明多个数组和多个变量

int i,j,k,n,m1[10],m2[20];

方括号中常量表达式表示数组元素的个数,如number[5]表示数组number有5个元素。但是其下标从0开始计算。因此5个元素分别为:

int number[5];
number[0];
number[1];
number[2];
number[3];
number[4];

访问数组元素时,下标的取值范围为 0≤index<length 过大或过小都会越界,导致数组溢出,发生不可预测的情况,我们将在后续小节重点讨论,请大家务必要引起注意。

数组名不能与其它变量名相同。如:

int cArray; 
float cArray[10]; //错误

数组长度 length 最好是整数或者常量表达式,例如 10、20*4 等,这样在所有编译器下都能运行通过;如果 length 中包含了变量,例如 n、4*m 等,在某些编译器下就会报错,我们将在后续小节专门讨论这点。

#define AI 3 //定义符号常量                              
int cArray[1+2]; //定义数组
int number[8+AI]; //定义数组
// 不建议:
int i=5;
int number[i];

2.2 一维数组初始化

给一维数组初始化就是给一维数组赋予初值。初始化的一般格式如下:

类型说明符 数组标识符[常量表达式]={1,2,3,4};
//{}中间的各个值就是各元素的初值,各值之间用英文逗号隔开,定义结束后,用英文分号结束此句代码。例如:
int number[5]={1,2,3,4,5};
// number[0]=1, number[1]=2, number[2]=3, number[3]=4, number[4]=5

在C语言中,对一维数组的初始化可以用以下几种方法实现:

//1.在定义数组时直接对数组元素赋初值,例如:
int iArray[8]={1,2,3,4,5,6,7,8};
//经过上面的定义和初始化之后,数组中的元素
//iArray[0]=1,iArray[1]=2,iArray[2]=3,iArray[3]=4,iArray[4]=5,iArray[5]=6,iArray[6]=7,iArray[7]=8

//2.只给一部分元素赋值,未赋值的部分元素值为0
int iArray[8]={1,2,3};
//经过上面的定义和初始化之后,数组中的元素
//iArray[0]=1,iArray[1]=2,iArray[2]=3,iArray[3]=0,iArray[4]=0,iArray[5]=0,iArray[6]=0,iArray[7]=0

//3.在对全部数组元素赋初值时可以不指定数组长度
int iArray[]={1,2,3,4};

//4.先定义数组再给数组赋值
int a[4];
a[0]=120;
a[1]=1345;
a[2]=1700;
a[3]=122;

2.3 一维数组的引用

数组定义完成后就要使用该数组,可以通过引用数组元素的方式使用该数组中的元素。数组元素表示的一般形式如下:

数组标识符[下标]

其中的下标可以是整型常量和整型表达式。如果为小数时,C编译器会自动取整,例如:
在这里插入图片描述
这段代码的第2行是引用数组,其中 iArray 是数组变量的名称,2为数组的下标。前面介绍过数组的下标是从0开始的,也就是说下标为0表示的是第一个数组元素。因此第3个元素下标是2,所以这句引用的是数组 iArray 的第3个元素。在C语言中只能逐个地使用下标变量,而不能一次引用整个数组。例如,逐个输出数组元素,代码如下:
在这里插入图片描述
这段代码实现的功能是输出数组 iArray 的各个元素,使用 iArray[i] 引用数组是合法的。但是:
在这里插入图片描述
这段代码也是想要输出数组各元素,但是它不是逐个输出,而是用一条语句输出数组,这样就是不合法的,不能输出数组各个元素值。示例: 使用一维数组输出某高中班级前5名的总成绩,代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:01-array.c
*   创 建 者:AmoXiang
*   创建日期:2023年10月10日 15:32:08
*   描    述:
*
================================================================*/


#include <stdio.h> //包含头文件
int main(){ //主函数
    int grade[5]; //定义数组
    int i = 0, j = 0;
    // 从控制台读取用户输入
    printf("请输入前5名各学生成绩: \n");
    for(;i<5;i++){ //输入学生成绩
        printf("第%d名成绩: ", i + 1);
        scanf("%d", &grade[i]); //注意取地址符&,不要遗忘
    }
    // 依次输出数组元素
    printf("前5名各学生成绩如下: \n");
    for(;j<5;j++){
        printf("第%d个成绩是: %d\n", j+1, grade[j]);
    }
    return 0;    
}

程序运行结果如下图所示:
在这里插入图片描述

三、二维数组

在第二小节讲解了一维数组,一维数组的下标只有一个,而如果下标是两个呢?在C语言中,将下标是两个的称为二维数组,例如 Array[m][n] 表示第m行第n列。例如,一个书柜布局如下图所示,利用书柜的行、列能够快速找到书的位置,而二维数组就类似行和列。
在这里插入图片描述

3.1 二维数组的定义

二维数组的声明与一维数组类似,一般形式如下:

数据类型 数组名[常量表达式1][常量表达式2];
// "常量表达式1"被称为行下标 "常量表达式2" 被称为列下标
// 如果有二维数组array[n][m],则二维数组的下标取值范围如下:
// 行下标的取值范围0~n-1 列下标的取值范围0~m-1 二维数组的最大下标元素是array[n-1][m-1]

例如,定义一个3行5列的整型数组,代码如下:

int array[3][5];//这一行代码说明了一个3行5列的数组,数组名为array,其下标变量的类型为整型。
//该数组的下标变量共有3×5个,即
array[0][0] array[0][1] array[0][2] array[0][3] array[0][4]
array[1][0] array[1][1] array[1][2] array[1][3] array[1][4]
array[2][0] array[2][1] array[2][2] array[2][3] array[2][4]

在C语言中,二维数组是按行排列的,即按行顺次存放,先存放 array[0] 行,再存放 array[1] 行。每行中的5个元素,也是依次存放。

3.2 二维数组初始化

在C语言中,对二维数组的初始化可以用以下几种方法实现:

//1.可以将所有数据写在一个大括号内,按照数组元素排列顺序对元素赋值
int array[2][2]={1,2,3,4};
//表示的二维数组形式如下:
1 2 
3 4 // 即array[0][0]的值是1,array[0][1]的值是2,array[1][0]的值是3,array[1][1]的值是4

//2.在为所有元素赋初值时,可以省略行下标,但是不能省略列下标
int array[][3]={1,2,3,4,5,6};//系统会根据数据的个数进行分配,一共有6个数据,而数组每行分为3列,当然可以确定数组为2行 形式:
1 2 3
4 5 6

//3.也可以分行给数组元素赋值
int array[2][3]={{1,2,3},{4,5,6}};

//4.在分行赋值时,可以只对部分元素赋值,未被赋值的元素系统默认的值为0
int array[2][3]={{1,2},{4,5}};

//5.二维数组也可以直接对数组元素赋值 这种赋值的方式就是使用数组引用的数组中的元素
int array[2][2];
array[0][0] = 1;
array[0][1] = 2; 
array[1][0] = 1;
array[1][1] = 2;

3.3 二维数组的引用

二维数组元素的引用一般形式为:

//不管是行下标还是列下标,其索引都是从0开始的
数组名[行下标][列下标]; //说明:二维数组的下标可以是整型常量或整型表达式
int array[2][2]={{5,2},{5,4}};//定义二维数组
array[1][1];//引用二维数组元素

例如:用二维数组求下表中分科的平均成绩。

具体代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:02-array.c
*   创 建 者:AmoXiang
*   创建日期:2023年10月10日 17:09:13
*   描    述:
*
================================================================*/

#include <stdio.h>
int main() {
  int k, l, arr[3][5]; // 定义变量和二维数组
  int score = 0, course[3];//定义变量和二维数组
  printf("请输入成绩: \n");
  for (k = 0; k < 3; ++k) { //遍历二维数组行
    for (l = 0; l < 5; ++l) { //遍历二维数组列
      printf("array[%d][%d]=", k, l);
      scanf("%d", &arr[k][l]);
      score += arr[k][l]; //计算成绩
    }
    course[k] = score / 5; //求每科的平均成绩
    score = 0;//重新赋值
  }
  printf("数学的平均成绩是(取整数): %d\n", course[0]);
  printf("语文的平均成绩是(取整数): %d\n", course[1]);
  printf("英语的平均成绩是(取整数): %d\n", course[2]);
  return 0;
}

程序运行结果如下图所示:
在这里插入图片描述

四、C语言数组是静态的,不能插入或删除元素

在C语言中,数组一旦被定义后,占用的内存空间就是固定的,容量就是不可改变的,既不能在任何位置插入元素,也不能在任何位置删除元素,只能读取和修改元素,我们将这样的数组称为 静态数组。 反过来说,如果数组在定义后可以改变容量,允许在任意位置插入或者删除元素,那么这样的数组称为 动态数组。 Python,JavaScript 等解释型的脚本语言一般都支持动态数组,而 C,C++,Java 等编译型的语言一般不支持动态数组。总之,C语言中的数组是静态的,一旦定义后长度就不能改变了,大家要注意这一点,不要尝试去插入或删除元素。如果由于项目要求,必须要在数组中插入或者删除元素,只能再造一个新数组!

C语言数组为什么是静态的?

不能插入和删除数组元素有时候会非常麻烦,比如一个数组保存了某个班级的学生学号,现在有一名学生退学了,就得把 TA 从数组中剔除,但是C语言并不支持这么做,这就给编程带来了不小的麻烦。数组元素都是紧挨着排布的,中间没有空隙,不管是插入元素还是删除元素,都得移动该元素后面的内存:在第 i 个元素后面插入一个新元素时,第 i 个元素后面的所有元素都要往后移动一个元素的位置,从而给新元素腾出位置来。如果该数组后面紧跟的是其它有用数据,那么为了防止覆盖有用数据,还不敢直接往后移动元素,必须得重新开辟一块内存,把所有的元素都复制过去。删除第 i 个元素就比较简单了,不管三七二十一,把第 i 个元素后面的所有元素都向前移动即可。插入和删除数组元素都要移动内存,甚至重新开辟一块内存,这是相当消耗资源的。如果一个程序中有大量的此类操作,那么程序的性能将堪忧,这有悖于「C语言非常高效」的初衷,所以C语言并不支持动态数组。另外,很多时候我们需要把数组的地址保存到一个变量里面(等大家学到指针时就会见到这种情况),如果数组重新开辟了内存,而变量里面的地址不跟着改变的话,后续再使用该变量就会导致错误。让C语言本身去维护这些变量的值,以保持同步更新,这又是不可能做到的,所以这个矛盾无法从根本上解决。

总之,为了保证程序执行效率,为了防止操作错误,C语言只支持静态数组,不支持动态数组。

五、C语言数组的越界和溢出

5.1 数组越界

C语言数组是静态的,不能自动扩容,当下标小于零或大于等于数组长度时,就发生了 越界(Out Of Bounds), 访问到数组以外的内存。如果下标小于零,就会发生 下限越界(Off Normal Lower); 如果下标大于等于数组长度,就会发生 上限越界(Off Normal Upper)。

C语言为了提高效率,保证操作的灵活性,并不会对越界行为进行检查,即使越界了,也能够正常编译,只有在运行期间才可能会发生问题。请看下面的代码:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:04-array.c
*   创 建 者:AmoXiang
*   创建日期:2023年10月11日 10:30:55
*   描    述:
*
================================================================*/


#include <stdio.h>
int main() {
  int a[3] = {101, 201, 301}, i;
  for (i = -2; i <= 4; i++) {
    printf("a[%d]=%d\n", i, a[i]);
  }
  return 0;
}

程序运行结果如下图所示:
在这里插入图片描述
越界访问的数组元素的值都是不确定的,没有实际的含义,因为数组之外的内存我们并不知道是什么,可能是其它变量的值,可能是函数参数,可能是一个地址,这些都是不可控的。

由于C语言的 放任 我们访问数组时必须非常小心,要确保不会发生越界。每个C语言程序员的生涯中都遇到过越界错误,我拿项上人头作保证,所以千万不要大意,因为越界错误有时候不容易发现,也不容易复现。当发生数组越界时,如果我们对该内存有使用权限,那么程序将正常运行,但会出现不可控的结果(如上例所示);如果我们对该内存没有使用权限,或者该内存压根就没有被分配,那么程序将会崩溃。

5.2 数组溢出

当赋予数组的元素个数超过数组长度时,就会发生 溢出(Overflow)。 如下所示:

//数组长度为3,初始化时却赋予5个元素,超出了数组容量,所以只能保存前3个元素,后面的元素被丢弃
int a[3] = {1, 2, 3, 4, 5};

一般情况下数组溢出不会有什么问题,顶多是丢失多余的元素。但是当以字符串的形式输出字符数组时,就会产生不可控的情况,请看下面的代码:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:04-array.c
*   创 建 者:AmoXiang
*   创建日期:2023年10月11日 10:30:55
*   描    述:
*
================================================================*/


#include <stdio.h>
int main()
{
  char str[5] = "https://blog.csdn.net/xw1680?";
  puts(str);
  return 0;
}

程序运行结果如下图所示:
在这里插入图片描述
字符串的长度大于数组长度,数组只能容纳字符串的前面一部分,也就是 "https" 即使编译器在最后添加了 '\0' 它也保存不到数组里面,所以 printf() 扫描数组时不会遇到结束符 '\0' 只能继续向后扫描。而后面内存中的数据我们不知道是什么,字符能否识别,何时遇到 '\0' 这些都是不确定的。当字符无法识别时,就会出现乱码,显示奇怪的字符。由此可见,在用字符串给字符数组赋值时,要保证数组长度大于字符串长度,以容纳结束符 '\0'

至此今天的学习就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习C语言的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!


在这里插入图片描述

    好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
    如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞评论收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
 编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!

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

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

相关文章

第一个2DGodot游戏-从零开始-逐步解析

视频教程地址&#xff1a;https://www.bilibili.com/video/BV1Hw411v78Y/ 前言 大家好&#xff0c;这一集我将要带领大家完成官方文档里的第一个2DGodot游戏&#xff0c;从零开始&#xff0c;逐步解析&#xff0c;演示游戏的制作全过程&#xff0c;尽量让&#xff0c;就算是新…

C++ - 包装器 - bind()函数

包装器 在 C 当中可能会有各种各样的可调用类型&#xff0c;比如 函数指针&#xff0c;仿函数&#xff0c;lambda 等等&#xff0c;那么这么多的可调用类型&#xff0c;我们在使用的时候就会犯迷糊&#xff0c;那可不可以统一控制一下呢&#xff1f; function包装器&#xff…

关于SSA算法中矩阵的3种运算:转置、求逆、相乘

1、矩阵转置 // 矩阵转置(二维矩阵)public static double[][] transposeTwo(double[][] matrix) {int rows matrix.length;int cols matrix[0].length;double[][] transposedMatrix new double[cols][rows];for (int i 0; i < rows; i) {for (int j 0; j < cols; j)…

一篇博客带你学会关于Vuex使用

前言&#xff1a; 在我们之前我们的学习vue知识中&#xff0c;我们组件传递方式有父传子&#xff0c;子传父&#xff0c;这两种方法传递参数复杂&#xff0c;所以我们今天来学习Vuex&#xff0c;就可以解决这个传递的问题&#xff01;&#xff01;&#xff01; 一&#xff0c;V…

【算法思考】端到端实例分割模型 SOLO

目录 背景工作总结 背景 不同于语义分割&#xff0c;实例分割不仅需要输出图像的语义蒙版&#xff0c;还要对图像中不同的实例作区分。如下图所示&#xff0c;实例分割任务需要多不同的羊做区分&#xff0c;输出不同的实例蒙版。 由于图片中实例个数的不确定性&#xff0c;实例…

第二章 C++的输出

系列文章目录 第一章 C的输入 文章目录 系列文章目录前言一、个人名片二、cout三、printf总结 前言 今天来学C的输出吧&#xff01; 一、个人名片 二、cout cout 三、printf printf 总结 最近懒得写博客怎么办&#xff1f;

【技术研究】环境可控型原子力显微镜超高真空度精密控制解决方案

摘要&#xff1a;针对原子力显微镜对真空度和气氛环境精密控制要求&#xff0c;本文提出了精密控制解决方案。解决方案基于闭环动态平衡法&#xff0c;在低真空控制时采用恒定进气流量并调节排气流量的方法&#xff0c;在高真空和超高真空控制时则采用恒定排气流量并调节进气流…

Docker系列--网络的配置

原文网址&#xff1a;Docker系列--网络的配置_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker的网络的配置。 官网网址 https://docs.docker.com/engine/reference/commandline/network/ 网络的默认设置 Docker启动之后&#xff0c;系统中会产生一个名为docker0的…

2015架构真题(五十)

供应链中信息流覆盖了供应商、制造商和分销商&#xff0c;信息流分为需求信息流和供应信息流&#xff0c;&#xff08;&#xff09;属于需求信息流&#xff0c;&#xff08;&#xff09;属于供应信息流。 库存记录生产计划商品入库单提货发运单 客户订单采购合同完工报告单销售…

Leetcode.2867 统计树中的合法路径数目

题目链接 Leetcode.2867 统计树中的合法路径数目 rating : 2428 题目描述 给你一棵 n n n 个节点的无向树&#xff0c;节点编号为 1 1 1 到 n n n 。给你一个整数 n n n 和一个长度为 n − 1 n - 1 n−1 的二维整数数组 e d g e s edges edges &#xff0c;其中 e d g …

Matlab地理信息绘图—风玫瑰图

文章目录 风玫瑰图的作用Matlab代码实现结果展示 风玫瑰图的作用 风玫瑰图&#xff08;Wind Rose Plot&#xff09;是一种用于可视化风向和风速分布的图表。它通常以极坐标形式呈现&#xff0c;其中角度表示风向&#xff0c;半径表示风速的频率或相对概率。风玫瑰图对于理解和呈…

项目log日志mysql记录,熟悉python的orm框架

直接在项目里面创建一个class&#xff0c;这个类对应着mysql里面的表 我们运行项目&#xff0c;可以自动建立表 在.env中找到mysql的配置信息&#xff0c;这个是在NB服务器上运行的mysql&#xff0c;localhost需要变成NB服务器的ipv4地址 使用Mysql工具连接查看&#xff0c;连…

【Java学习之道】继承与多态

引言 本文将介绍面向对象编程的核心概念——继承与多态。对于初学者来说&#xff0c;掌握这些基本概念是迈向Java高手的第一步。接下来&#xff0c;让我们一起揭开继承与多态的神秘面纱&#xff0c;感受它们的魅力吧&#xff01; 一、继承 继承是面向对象编程的一个重要特性…

C++学习day5

目录 作业&#xff1a; 1> 思维导图 2> 多继承代码实现沙发床 1>思维导图 2> 多继承代码实现沙发床 #include <iostream>using namespace std; //创建沙发类 class sofa { private:string sitting; public:sofa(){cout << "sofa的无参构造函数…

算法leetcode|82. 删除排序链表中的重复元素 II(rust重拳出击)

文章目录 82. 删除排序链表中的重复元素 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 82. 删除排序链表中的重复元素 II&#xff1…

开发者职场“生存状态”大调研报告分析 - 第一版

听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…

三轮技术面 +HR 面,字节跳动面试也不过如此......

前言 人人都有大厂梦&#xff0c;对于软件测试人员来说&#xff0c;BAT 为首的一线互联网公司肯定是自己的心仪对象&#xff0c;毕竟能到这些大厂工作&#xff0c;不仅薪资高待遇好&#xff0c;而且能力技术都能够得到提升&#xff0c;最关键的是还能够给自己镀上一层金&#…

Unity中Shader的光照衰减

文章目录 前言一、衰减原理1、使用一张黑白渐变贴图用于纹理采样2、把模型从世界坐标转化为灯光坐标&#xff08;即以灯光为原点的坐标系&#xff09;3、用转化后的模型坐标&#xff0c;对黑白渐变纹理进行纹理采样4、最后&#xff0c;把采样后的结果与光照模型公式的结果相乘输…

PBA.客户需求分析管理

1 需求的三个层次: Requirement/Wants/Pains 大部分人认为&#xff0c;产品满足不了客户需要&#xff0c;是因为客户告知的需求是错误的&#xff0c;这听起来有一些道理&#xff0c;却没有任何意义。不同角色对于需求的理解是不一样的。在客户的需求和厂家的需求之间必然有一定…

分布式文件服务器——Windows环境MinIO的三种部署模式

上节简单聊到MinIO&#xff1a;分布式文件存储服务——初识MinIO-CSDN博客&#xff0c;但没具化&#xff0c;本节开始展开在Windows环境下 MinIO的三种部署模式&#xff1a;单机单节点、单机纠删码、集群模式。 部署的几种模式简要概括 所谓单机单节点模式&#xff1a;即MinI…