我是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
答案 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。