I am new to C language and trying to figure out the meaning of the following code.
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
It depends on the type of
msize is a pointer, it tests whether it is
msize is not a pointer, it tests whether it is
This distinction may seem pedantic, but it's important. While
NULL is actually
0 on most systems, the C standard allows it to be any other value.
I did some further reading, because I started to doubt whether my understanding above is correct.
Here are relevant parts of the C standard.
§188.8.131.52 Unary arithmetic operators
(5) The result of the logical negation operator
!is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type
int. The expression
!Eis equivalent to
(3) An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant. 66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
(6) Any pointer type may be converted to an integer type. Except as previously speciﬁed, the result is implementation-deﬁned. If the result cannot be represented in the integer type, the behavior is undeﬁned. The result need not be in the range of values of any integer type.
Footnotes: 66 The macro
NULLis deﬁned in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
As you can see, 0 is kind of a magic number in C. For systems with a non-zero
NULL, I expect that the actual behaviour of
!msize may be implementation-defined. In any case, this is all a bit nit-picky.
I tracked down the source of your example in the paper: Undeﬁned Behavior: What Happened to My Code?. The text discussing your example states:
As mentioned earlier, at the instruction set level, x86 raises an exception for a division by zero [17, 3.2], while MIPS [22, A.6] and PowerPC [15, 3.3.38] silently ignore it. A division by zero in C is undefined behavior [19, 6.5.5], and a compiler can thus simply assume that the divisor is always non-zero.
Figure 1 shows a division-by-zero misuse in the Linux kernel. From the programmer’s comment it is clear that the intention is to signal an error in case msize is zero. When compiling with GCC, this code behaves as intended on an x86, but not on a PowerPC, because it will not generate an exception. When compiling with Clang, the result is even more surprising. Clang assumes that the divisor msize must be non-zero—on any system—since otherwise the division is undefined. Combined with this assumption, the zero check !msize becomes always false, since msize cannot be both zero and non-zero. The compiler determines that the whole block of code is unreachable and removes it, which has the unexpected effect of removing the programmer’s original intention of guarding against the case when msize is zero.
So in your case, the answer you really needed was yes: it tests whether
msize is 0.