C语言如果声明

时间:2014-02-02 21:50:12

标签: c

我是C语言的新手并试图找出以下代码的含义。

在这里if (!msize)检查msize是否为零或msize是否为空?

if (!msize)
    msize = 1 / msize; /* provoke a signal */

//Example 1: A division-by-zero misuse, in lib/mpi/mpi-pow.c of the Linux kernel, where the entire code will be optimized away. 
//Compilers, GCC 4.7 and Clang 3.1

1 个答案:

答案 0 :(得分:4)

取决于msize的类型。

  • 如果msize是指针,则会测试它是NULL

  • 如果msize不是指针,则会测试它是0

这种区别可能看起来很迂腐,但这很重要。虽然NULL在大多数系统上实际上都是0,但C标准允许它为任何其他值。


我做了一些进一步的阅读,因为我开始怀疑我的理解是否正确。

以下是C标准的相关部分。

  

§6.5.3.3一元算术运算符

     

(5)逻辑否定运算符 ! 的结果为0,如果其值为   操作数比较不等于0,1如果其操作数的值比较则为1   等于0.结果类型为int。表达式 !E 是等效的   到 (0==E)

     

§6.3.2.3指针

     

(3)具有值0的整数常量表达式,或这样的表达式   强制转换为 void * ,称为空指针常量 66 )如果为null   指针常量被转换为指针类型,由此产生   指针,称为空指针,保证比较不等于a   指向任何对象或函数的指针。

     

(6)任何指针类型都可以转换为整数类型。除了   以前指定的,结果是实现定义。如果   结果不能用整数类型表示,行为是   理解过程科幻定义。结果不必在任何整数的值范围内   类型。

     

脚注: 66 NULL < stddef.h> (以及其他标题)中定义为空指针常量;见7.19。

如您所见,0是C中的幻数。对于具有非零NULL的系统,我期望!msize的实际行为可能是实现定义的。无论如何,这都有点挑剔。

我在论文中追踪了你的例子的来源:Undefined Behavior: What Happened to My Code?。讨论你的例子的文字说明:

  

如前所述,在指令集级别,x86引发了一个   零除[17,3.2]的异常,而MIPS [22,A.6]和   PowerPC [15,3.3.38]默默地忽略它。在C中除以零是   未定义的行为[19,6.5.5],因此编译器可以简单地假设   除数总是非零。

     

图1显示了Linux内核中的逐个为零的滥用行为。来自   程序员的评论很明显,目的是发出信号   msize为零时出错。使用GCC编译时,此代码   在x86上表现得像预期的那样,但在PowerPC上却没有,因为它会   不生成异常。用Clang编译时,结果是   更令人惊讶的是。 Clang假定除数msize必须是   在任何系统上都是非零的 - 否则分割是不确定的。   结合这个假设,零检查!msize变为总是   false,因为msize不能同时为零和非零。编译器   确定整个代码块无法访问并删除它,   它具有删除程序员原始的意外效果   msize为零时防止案件的意图。

所以在你的情况下,你真正需要的答案是肯定的:它测试msize是否为0。