3

在 $WORK 中处理 COBOL 程序时,我遇到了一个奇怪的语句。

我们有一个段落正在打开一个游标(来自 DB2),并在它上面循环直到它遇到 EOT(在伪代码中):

... working storage ...
01  I                       PIC S9(9) COMP VALUE ZEROS.
01  WS-SUB                  PIC S9(4) COMP VALUE 0.

... code area ...
PARA-ONE.                                                
    PERFORM OPEN-CURSOR
    PERFORM FETCH-CURSOR

    PERFORM VARYING I FROM 1 BY 1 UNTIL SQLCODE = DB2EOT                        
        do stuff here...
    END-PERFORM                                           

    COMPUTE WS-SUB = I + 0                            
    PERFORM CLOSE-CURSOR

    ... do another loop using WS-SUB ...

我想知道为什么那条COMPUTE WS-SUB = I + 0线在那里。我的理解是,由于它上面的 perform 块,它I总是至少是1(即,即使有一个 EOT 开始,I也会在初始迭代中设置为一个)。

那条COMPUTE线甚至需要吗?它是否在做一些我不知道的隐式转换?为什么会在那里?你为什么不MOVE I TO WS-SUB呢?

4

3 回答 3

7

称其为愚蠢,但使用一些编译器(具有有效的正确选项),给定

 01  SIGNED-NUMBER   PIC S99 COMP-5 VALUE -1.
 01  UNSIGNED-NUMBER PIC  99 COMP-5.
      ... 
      MOVE SIGNED-NUMBER TO UNSIGNED-NUMBER
      DISPLAY UNSIGNED-NUMBER

结果:255。但是......

COMPUTE UNSIGNED-NUMBER = SIGNED-NUMBER + ZERO

结果:1(无符号)

因此,要回答您的问题,这可以归类为使用将有符号数字转换为无符号数字的技术。但是,在您提供的代码示例中,它根本没有意义。

于 2011-12-14T23:53:58.113 回答
0

请注意,“I”的定义(可能)由一位程序员编写,而 WS-SUB 的定义由另一位程序员编写(命名不同,VALUE 子句出于相同目的而不同)。

程序员 2 看起来像“老派”:PIC S9(4),签名并占用了所有“适合”半字的数字。根据可能的值范围,S9(9) 可能“远远超过顶部”,但这些事情根本不关心程序员 1。

程序员 2 可能担心将 S9(9) COMP 用于需要(可能很多)少于 9999 个“事物”的事物。“在不更改现有代码的情况下,我将‘高效’”。在我看来,该字段不太可能被定义为无符号。

具有九位数字的 COMP/COMP-4 在用于计算时确实会降低性能。尝试“添加 1”到 9(9) 和 9(8) 和 9(10) 并比较生成的代码。如果您可以有九位数字,请使用 9(10) 进行定义,否则使用 9(8) 定义,如果您需要完整字词。

程序员 2 对此有所了解。

+ 0 的 COMPUTE 可能是故意的。为什么程序员 2 那样使用 COMPUTE(原始问题)?

现在它会变得复杂。

大型机上有两种“类型”的“二进制”字段:那些将包含受 PICture 子句限制的值(USAGE BINARY、COMP 和 COMP-4);那些包含受字段大小限制的值(USAGE COMP-5)。

使用 BINARY/COMP/COMP-4,字段的大小由 PICture 确定,可以保存的值也是如此。PIC 9(4) 是一个半字,最大值为 9999。PIC S9(4) 是一个半字,其值为 -9999 到 +9999。

使用 COMP-5 (Native Binary),PICture 只是决定字段的大小,字段的所有位都与字段的值相关。图 9(1) 至 9(4) 定义半字,图 9(5) 至 9(9) 定义全字,图 9(10) 至 9(18) 定义双字。PIC 9(1) 最多可容纳 65535,S9(1) -32,768 到 +32,767。

一切都很好。然后是编译器选项TRUNC。这有三个选项。STD,默认值,BIN 和 OPT。

BIN 可以认为影响最深远。BIN 使 BINARY/COMP/COMP-4 的行为类似于 COMP-5。实际上,一切都变成了 COMP-5。二进制字段的图片被忽略,除了确定字段的大小(奇怪的是,使用 ON SIZE ERROR,当超过 PICture 的最大值时“错误”)。IBM Enterprise Cobol 中的 Native Binary 主要(但不限于)生成“最慢”的代码。截断是字段大小(半字、全字、双字)。

默认情况下,STD 是“标准”截断。这将截断为“图片”。因此,它是“十进制”截断。

OPT 是为了“性能”。使用 OPT,编译器会以任何方式截断特定“代码序列”的最“高性能”。这可能意味着中间值和最终值可能具有“位设置”,这些“位”位于 PICture 的“范围之外”。但是,当用作源时,二进制字段将始终仅反映 PICture 指定的值,即使设置了“多余”位也是如此。

使用 OPT 时,所有二进制字段“符合 PICture”非常重要,这意味着代码绝不能依赖于 PICture 定义之外设置的位。

注意:即使使用了 OPT,OPTimizer(OPT(STD) 或 OPT(FULL))仍然可以提供进一步的优化。

这一切都很好。

但是,如果您“混合”TRUNC 选项,或者如果 CALLing 程序中的二进制定义与 CALLed 程序中的不同,则很容易出现“pickle”。如果同一运行单元中的模块使用不同的 TRUNC 选项编译,或者如果文件上的二进制字段使用一个 TRUNC 选项写入,然后使用另一个读取,则可能会发生“混合”。

现在,我怀疑程序员 2 遇到了这样的事情:要么,使用 TRUNC(OPT),他们注意到一个字段中的“多余位”并认为需要处理它们,或者,通过运行中的选项“混合” -unit 或“跨文件使用”他们注意到“多余的位”需要对其进行处理(即“删除混合”)。

程序员 2 开发了 COMPUTE A = B + 0 来“处理”特定问题(感知的或实际的),然后将其普遍应用到他们的工作中。

这是一种“猜测”,或者更好的是,一种与已知信息一起工作的“合理化”。

这是一个“假”修复。没有问题(TRUNC(OPT) 工作的正常方式)或正确的解决方案是跨模块/文件使用的 TRUNC 选项的“规范化”。

不希望现在有很多人匆忙离开并将 COMPUTE A = B + 0 放入他们的代码中。首先,他们不知道自己为什么要这样做。对于延续,这是错误的做法。

当然,不要只是从您找到的任何这些中删除“+ 0”。如果存在 TRUNC 的“混合”,则程序可能会停止“工作”。

在一种情况下,我对 BINARY/COMP/COMP-4 使用了“加零”。这是在一个“米老鼠”程序中,这个程序没有任何目的,只是为了尝试一些东西。在这里,我将它用作“欺骗”优化器的方法,否则优化器可能会看到不变的值,因此会生成代码以使用文字结果,因为所有值在编译时都是已知的。(我从 PhilinOxford 获得的一种可能“更简洁”和更灵活的方法是在该领域使用 ACCEPT)。可以肯定的是,有问题的代码并非如此。

于 2013-01-21T01:56:19.917 回答
0

我想知道是否有源的测试版本

COMPUTE WS-SUB = I + 0
    ON SIZE ERROR
        DISPLAY "WS-SUB overflow"
        STOP RUN
END-COMPUTE

当开发人员满意并清理时丢弃范围测试?MOVE 不允许声明性 SIZE 语句。这就是我所看到的一个原因。或者也许是开发人员使用 COMPUTE 移动的习惯,作为一个微妙的提醒,让他们质疑每一步都需要防御性代码?正如乔指出的那样,也许不知道 SIZE 子句在没有 + 0 的情况下同样有效吗?或者维护者因一个错误而苦苦挣扎,并且在测试后有一个从 1 到 0 的纠正性变化?

于 2013-01-22T05:57:00.720 回答