必须评估断言? [英] Must evaluate assertion?

查看:64
本文介绍了必须评估断言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



无论是否定义了NDEBUG,都必须对一个断言表达式

进行评估吗?例如,以下代码完全可以吗?


#define NDEBUG


#include< assert.h>


int main(无效)

{

int array [5];


int * p =数组+5;


断言( - p);


* p = 3;


返回0;

}


依赖断言表达式的评估是否明智,或者它是否b / b
最好将任何副作用移到断言之外,例如:


--p;断言(p);


而不是:


断言( - p);


-


Frederick Gotham

解决方案

Frederick Gotham问:


无论是否定义了NDEBUG,是否必须首先评估断言表达式

?例如,以下代码是否完全正常?


#define NDEBUG


#include< assert.h>

int main(void)

{

int array [5];

int * p = array + 5;

断言( - p);

* p = 3;


返回0;

}



标准(c99)说:

如果NDEBUG被定义为

点的宏名称包含< assert.h>的源文件,

断言宏的定义简单为

#define assert(ignore)((void)0)


因此,参数未被评估,(断言是宏,而不是

函数)。由于这种行为是强制性的,因此很容易检查。

Szabolcs Borsanyi


如果我弄错了,请纠正我。


Frederick Gotham写道:


无论是否定义了NDEBUG,都必须始终评估断言表达式

? [...]



编号如果在< assert.his包含之前定义了NDEBUG,则

断言(x)为否-op和`x''未被评估。从来没有。


依靠对断言表达式的评估是明智的,还是将b / b $ b更好地移动任何副作用在断言之外,例如:


--p;断言(p);


而不是:


断言( - p);



使用前者,而不是后者。在断言的表达中使用

副作用是不明智的。


-

Eric Sosman es*****@acm-dot-org.inva lid


Frederick Gotham schrieb:


无论是否定义了NDEBUG,都必须首先评估断言表达式

?例如,以下代码完全可以吗?



不,不。其他人已经告诉过你了。


依靠对断言表达式的评估是明智的,还是会更好地移动
对断言之外的任何副作用,例如:


--p;断言(p);


而不是:


断言( - p);



第一种方式肯定比第二种方式好,因为它会导致相同的程序行为。

请注意,在C90中,assert需要一个整数表达式作为参数,

所以上面的指针类型可能会失败。


我宁愿不鼓励在主控制流中使用断言。

考虑一下:

if(....)

{

/ *不应该发生* /

INTERNAL_ASSERT(0);

EmitInternalFatal(....);

CleanupAndDie();

}



....

默认值:

INTERNAL_ASSERT( 0,D \u!;);

EmitExternalFatal(....);

....

客户获取INTERNAL_ASSERT

不执行任何操作的版本,而开发人员使用版本的地方

使调试器停止运行(此版本差异可以是

隐藏选项)。通过这种方式,用户可以获得干净的中止,并且您可以获得调试帮助。

这是大多数人都同意的用途之一。

关于clc已经进行了几次长时间的讨论,关于

如何使用断言 - 只需在档案中阅读它们。

干杯

Michael

-

电子邮件:我的是/ at / gmx / dot / de地址。



Irrespective of whether NDEBUG is defined, must an assertion expression
always be evaluated? For instance, is the following code perfectly OK?

#define NDEBUG

#include <assert.h>

int main(void)
{
int array[5];

int *p = array + 5;

assert(--p);

*p = 3;

return 0;
}

Is it wise to rely on the evaluation of assertion expressions, or would it
be better to move any side-effects to outside of the assertion, such as:

--p; assert(p);

instead of:

assert(--p);

--

Frederick Gotham

解决方案

Frederick Gotham asked:

Irrespective of whether NDEBUG is defined, must an assertion expression
always be evaluated? For instance, is the following code perfectly OK?

#define NDEBUG

#include <assert.h>
int main(void)
{
int array[5];
int *p = array + 5;
assert(--p);
*p = 3;

return 0;
}

The standard (c99) says:
If NDEBUG is defined as a macro name at the
point in the source file where<assert.h>is included,
the assert macro is defined simply as
#define assert(ignore) ((void)0)

So, the argument is not evaluated, (assert is a macro and not a
function). As this behaviour is mandatory, it is very easy to check.
Szabolcs Borsanyi

Correct me if I get it wrong.


Frederick Gotham wrote:

Irrespective of whether NDEBUG is defined, must an assertion expression
always be evaluated? [...]

No. If NDEBUG is defined before <assert.his included,
assert(x) is a no-op and `x'' is not evaluated. Not ever.

Is it wise to rely on the evaluation of assertion expressions, or would it
be better to move any side-effects to outside of the assertion, such as:

--p; assert(p);

instead of:

assert(--p);

Use the former, not the latter. It is UNwise to have
side-effects in an assert-ed expression.

--
Eric Sosman
es*****@acm-dot-org.invalid


Frederick Gotham schrieb:

Irrespective of whether NDEBUG is defined, must an assertion expression
always be evaluated? For instance, is the following code perfectly OK?

No, and no. Others have already told you that.

Is it wise to rely on the evaluation of assertion expressions, or would it
be better to move any side-effects to outside of the assertion, such as:

--p; assert(p);

instead of:

assert(--p);

The first way certainly is better than the second in that it
always leads to the same programme behaviour.
Note that in C90, assert expects an integer expression as argument,
so the above can fail for p of pointer type.

I rather discourage the use of assert in your main control flow.
Consider this:
if (....)
{
/* Should not happen */
INTERNAL_ASSERT(0);
EmitInternalFatal(....);
CleanupAndDie();
}
or
....
default:
INTERNAL_ASSERT(0, "D\''uh!");
EmitExternalFatal(....);
....
where the customer gets the version where INTERNAL_ASSERT
does not do anything and the developers the version where it
makes the debugger stop (this version difference can be a
hidden option). This way, the users get a clean abort and you
get help for debugging.
This is one of the uses most people can agree to.
There have been several long discussions on clc about just
how to use assert -- just read them in the archives.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.


这篇关于必须评估断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆