为什么 Codesys 可以从非零值开始数组?

Mal*_*nko 1 codesys

在我使用 IFM PLC 的一些项目中,我遇到了以下代码:

someArray:ARRAY  [6..8] OF BYTE;
Run Code Online (Sandbox Code Playgroud)

当我在断点处检查数组时,我发现它具有三个元素:

someArray[6] = 0
someArray[7] = 0
someArray[8] = 0
Run Code Online (Sandbox Code Playgroud)

我一生都无法理解为什么有人会这样做,或者为什么这是可能的。我从来没有见过这样的事情。我没有进一步的来源可以帮助我理解它的用途(缺少部分),但这就是它的声明和使用方式。我查看了文档,也找不到原因。

为什么这是可能的,在什么情况下你会想要这样的数组?

Gui*_*rgy 6

CODESYS 有一篇文章

... 结构化文本基于 Pascal 编程语言 ...

Pascal 同样允许任何起始索引,例如:

temperature = array [-10 .. 50] of real;
Run Code Online (Sandbox Code Playgroud)

这就是codesys 允许这样做原因。

不过,这种功能的存在也是有原因的:

  • 大多数程序员都习惯数组索引从 0 开始,但是这里有一篇文章列出了从 1 开始计算索引的语言。它们中的大多数是供非程序员使用的,例如数学家、工程师等,codesys 也不例外(为什么梯形逻辑存在:P)。

  • 如果开发人员不厌其烦地允许从 0 或 1 开始,不妨将其扩展到用户想要的任何位置。

  • 您可能希望将数组中的索引与实际标识符相关联。例如,假设您有 2 个设备和一个由 2 个布尔值组成的数组(表示设备是否正在运行),并且这些设备放置在容器 #2 和 #3 中,而容器 #1 没有此类设备。您可以创建 2 个单独的变量(例如dev2, dev3),或者您可以创建一个 2 的数组并记住索引 0 代表设备 2,索引 1 代表设备 3,或者您可以创建一个大小为 4 的数组(0, 1, 2 , 3) 并忽略前 2 个元素,或者您可以创建一个从 2 到 3 包含 2 个元素的数组 ( :ARRAY [2..3] OF BOOL;)。

这种语言功能只是为您提供了更多表达意图的选项,如果您不喜欢它,则不必使用它(但请注意,如果您在函数中接受任何大小的数组,请不要忘记使用该LOWER_BOUND功能:D)

最后,如果您必须使用其他人的数组并且绝对讨厌它的起始索引不为 0 的想法,因为数组本质上是带有(编译时)元数据的指针,您可以将数组转换为指针,并将该指针用作一个数组,您必须从 0 开始访问它:

arr: ARRAY [7..13] OF INT := [7, 8, 9, 10, 11, 12, 13];
up_bound: DINT := UPPER_BOUND(arr, 1) - LOWER_BOUND(arr, 1);
ptr: POINTER TO INT := ADR(arr);
i: DINT;
str: STRING;

// ---

str := '[';
FOR i := 0 TO up_bound - 1 DO
    str := CONCAT(str, INT_TO_STRING(ptr[i]));
    str := CONCAT(str, ', ');
END_FOR
str := CONCAT(str, INT_TO_STRING(ptr[i]));
str := CONCAT(str, ']');
Run Code Online (Sandbox Code Playgroud)

上面例子的结果是:

STR |  字符串 |  '[7,8,9,10,11,12,13]'

  • 好答案!我不会抱怨这种语言,因为即使在 PLC 世界中,从 0 开始数组也是很常见的做法。我会咆哮那些做出这种选择而没有留下描述原因的评论的程序员。可能有,也可能没有。 (2认同)