我试图在这个例子中证明返回值为0(如果8不在数组中)或1(如果数组为8)。
int fi8(int *array, int size) {
int fi8 = 0;
int i = 0;
for(i = 0; i < length; ++i)
{
if(array[i] == 8)
fi8 = 1;
}
return fi8;
}
我创造了前后条件:
/*@ requires 0 <= size <= 100;
@ requires \valid(array+(0..size-1));
@ assigns \nothing;
@ ensures (\forall integer i; 0<= i < size && array[i] != 8) ==> (\result == 0);
@ ensures (\exists integer i; (0<= i < size && array[i] == 8)) && (\result == 1);
@*/
和循环不变量,因为Frama-C基于Hoare Logic:
/*@ loop invariant 0 <= i <= length;
@ loop invariant fi8 == 0 || fi8 == 1;
@ loop invariant (\forall integer i; 0<= i < size && array[i] != 8)
==> (fi8 == 0);
@ loop invariant (\exists integer i; (0<= i < size && array[i] == 8))
&& (fi8 == 1);
@ loop assigns i, fi8;
@*/
我很确定我在线路上遗漏了一些东西,我试图使用forall 并存在。 我花了好几个小时试图理解,我如何正确检查,是否在阵列上分配了任何值,但我觉得我被困在这里。 我非常感谢你的帮助:)。
答案 0 :(得分:3)
您的代码存在一些问题。首先,您似乎混合了size
和length
。我自由地在任何地方使用size
,否则这个代码甚至不会被C编译器接受,更不用说Frama-C了。其次,\forall integer i; 0<= i < size && array[i] != 8
(和相应的循环不变量)不正确。从字面上看,这意味着任何整数i
都验证两者,i
介于0
和 size
和{{ 1}}不是array[i]
。以8
为101
给出了这个命题的一个微不足道的反例。您要表达的是,对于任何整数i
,如果 i
介于i
和0
之间,则 size
不是array[i]
,表示为8
。另一方面,\forall integer i; 0<= i < size ==> array[i] != 8
连接器在&&
下使用时是正确的:这次我们确实想要找到\exists
,i
在i
的范围内数组和array[i]==8
。但是,您上次确认的第二个&&
不正确:您要说的是如果有这样的i
,那么\result == 1
,因此你必须在这里有一个含义:(\exists integer i; 0<= i < size && array[i] == 8) ==> (fi8 == 1)
最后一个问题是你的循环不变量。您正在重新使用它作为量化变量,而它已经是C变量,这通常不是一个好主意。事实上,这是一个真正的问题,因为您要表达的属性是,只要我们在8
和0
,i
之间没有看到fi8==0
(并且,如果看到8
,fi8==1
),i
是C变量。如果您在量化中使用j
,请参阅
loop invariant (\forall integer j; 0<= j < i ==> array[j] != 8) ==> (fi8 == 0);
loop invariant (\exists integer j; 0<= j < i && array[j] == 8) ==> (fi8 == 1);
所有证明义务均已解除。