访问不存在的数组索引

有必要将代码从一种语言重写为另一种语言,并且发现访问不存在的数组索引时,不同的语言会有不同的行为。 细节剪下。


图片

这是结构化文本中的示例代码,用于对工业控制器进行编程。 用这种语言编写的程序可以执行各种操作,从控制交通信号灯到控制核电站的过程。 尊重语言和平台的细节,因此代码可能看起来很不寻常。


VAR i: INT; OUT: INT; IN: ARRAY [0..4] of INT:= 1, 2, 3, 4, 5; END_VAR OUT := 0; FOR i:= 0 TO 4 DO OUT := OUT + IN[i]; END_FOR; 

这个程序做什么? 从输入信号读取数据,并将控制操作写入OUT变量。 该变量的值为15。现在,我们向程序中引入一些错误,特别是将一个元素放在数组中不存在的索引处并查看结果。


 VAR i: INT; OUT: INT; IN: ARRAY [0..4] of INT:= 1, 2, 3, 4, 5; END_VAR OUT := 0; FOR i:= -1 TO 4 DO OUT := OUT + IN[i]; END_FOR; 

变量OUT中的值= 15

这与错误之前相同。 该程序没有引发异常,而只是忽略了不存在的元素。 如果我们不意外处理异常并管理核反应堆的应急棒,这种行为对我们来说是可以接受的。 OUT变量的控制操作将与错误索引更改之前的操作相同。 如果这是短期故障,则系统将不会响应该错误,并且将继续稳定运行。 现在想象一下,其他编程语言中的不同程序执行相同的任务并比较结果。


在所有编程语言中,无错误索引的代码均以相同的方式执行,并且变量OUT的值始终为15。我们将仅考虑将错误归因于起始索引值为-1的代码。


Java脚本


 var IN = [ 1, 2, 3, 4, 5 ]; var OUT = 0; for (var i = -1; i <= 4; i++) { OUT += IN[i]; } console.log('OUT = '+ OUT); 

OUT = NaN

去吧


 package main import "fmt" func main() { IN := [5]int{ 1, 2, 3, 4, 5 } OUT := 0 for i := -1; i <= 4; i++ { OUT += IN[i] } fmt.Printf("OUT = %d", OUT) } 

紧急:运行时错误:索引超出范围

爪哇


 public class MyClass { public static void main(String args[]) { int[] IN = {1, 2, 3, 4, 5}; int OUT = 0; for (int i = -1; i <= 4; i++) OUT += IN[i]; System.out.printf("OUT = %d", OUT); } } 

线程“主”中的异常java.lang.ArrayIndexOutOfBoundsException:-1

p


 <?php $IN = [1, 2, 3, 4, 5]; $OUT = 0; for ($i=-1; $i<=4; $i++) { $OUT += $IN[$i]; } echo('OUT = '.$OUT); 

输出= 15
PHP注意:未定义的偏移量:-1

Python 3


 IN = [ 1, 2, 3, 4, 5 ]; OUT = 0; for i in range(-1, 5): OUT += IN[i]; print('OUT = {0:1d}'.format(OUT)); 

输出= 20

在Python中,支持负索引,并且编号从数组的末尾开始。


C / C ++


 #include<stdio.h> int main() { int IN[]= {1,2,3,4,5}; int OUT=0; int i; for (i=-1; i<=4; i++) { OUT += IN[i]; } printf("OUT = %i", OUT); return 0; } 

关于C ++语言,这是一个单独的故事。 如果要在受欢迎的网站上查看此示例,将得到以下结果:


http://codepad.org


OUT = -143484461

https://ideone.com/等。


输出= 15

https://www.jdoodle.com


输出= 14

在本文中,我不会详细介绍这些站点在哪些平台上使用哪些C / C ++编译器。 如果您在评论中分享您的意见,我将非常高兴。


C锐


 using System; class Program { static void Main() { int[] IN = new int[] { 1, 2, 3, 4, 5 }; int OUT = 0; for (int i = -1; i <= 4; i++) { OUT += IN[i]; } Console.Write("OUT of IN + y = "+ OUT); } } 

未处理的异常:
System.IndexOutOfRangeException:索引超出数组的范围。

结论


用任何编程语言编写代码时,都需要考虑使用该语言的数据结构的功能。 还请考虑程序中代码可能会“崩溃”的所有位置。 通常,在发生异常之后,程序代码无法再返回到错误行,并且可以在代码下方执行重要的操作。 因此,并非所有语言都适合解决某些问题或需要其他检查和代码分支。 在IEC标准的语言中,可以防止原始软件错误,因为在发生故障时通常没有人会超载控制器程序,并且在某些情况下此操作也可能是致命的。

Source: https://habr.com/ru/post/zh-CN415911/


All Articles