Ada单元素数组for循环倒数索引未抛CONSTRAINT_ERROR问题咨询
Ada单元素数组循环中
Index'Pred(Last)不触发异常的原因 问题场景
你有一个打印离散类型索引数组的Ada通用程序,逻辑是通过遍历到倒数第二个元素来避免最后输出多余逗号:
- 数组长度>1时(比如
IA),程序正常打印; - 数组长度=1时(比如
IA2),for循环里写的Index'Pred(IA'Last)没触发CONSTRAINT_ERROR,程序正常输出[0];但把这个表达式拿到循环外执行,就会直接抛出约束异常。
编译参数:Gnatstudio下用gprbuild -cargs -g -O0编译。
关键原因:Ada循环的范围处理规则
这是Ada语言的标准语义,和编译器优化无关(哪怕你开了-O0也一样):
当for循环的范围起始值大于结束值时,循环体不会执行,而且用于计算范围边界的表达式不会被实际求值。
对应到你的单元素数组场景:
单元素数组的First和Last是同一个值,假设为X。循环范围如果是IA2'First .. Index'Pred(IA2'Last),那起始值是X,结束值是X的前驱(必然小于X),此时起始值>结束值,循环被判定为空循环。既然循环不会执行,Index'Pred(IA2'Last)这个表达式根本不会被求值,自然不会触发异常。
但在循环外单独写这个表达式时,它会被直接求值,此时因为X没有合法的前驱(单元素数组的索引边界刚好是类型的极值),就会触发CONSTRAINT_ERROR。
额外说明
这个行为是Ada语言规范明确要求的,不是GNAT编译器的特殊处理。不管你是否开启优化,只要符合空循环的条件,范围边界的无效表达式就不会被执行,也就不会抛出异常。
内容的提问来源于stack exchange,提问作者Sidisyom
相关产品推荐
相关产品推荐

