On 2012-10-06, Vijay Mathew <vijay.the.lis...@gmail.com> wrote:
Not sure how an "implementation-defined conversion" translates to Common Lisp.
> I want to translate the following C code to Common Lisp:
> int main()
> char a = 255;
Char may be only 8 bits wide, and it may be signed, so that it only
goes up to 127.
> char b = 244;
Shifting a 1 bit into the sign bit of a signed type is undefined behavior.
> char c = (a << 8) | b;
Here the operand a is promoted to type int. If the value of a is negative,
the behavior is undefined right off the bat. ISO 9899:1999 says:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value of
the result is E1 × 2E2 , reduced modulo one more than the maximum
value representable in the result type. If E1 has a signed type and
nonnegative value, and E1 × 2E2 is representable in the result type,
then that is the resulting value; otherwise, the behavior is undefined.
[6.5.7 paragraph 4]
[2E2 above is an exponential notation: 2 to the power of E2]
If a is positive (255), then you still have a problem because int might be only
16 bits wide, and so a << 8 will shift a 1 into the sign bit. Undefined
> printf ("%d\n", c); // => -12
So this result is basically nonportable garbage.
Whereas this is mathematically correct.
> I tried this:
> (logior (ash 255 8) 244) ;; => 65524
If you want nonportable garbage in Lisp, you can, oh, modify a list literal!
Or embed a non-externalizable object into source code and compile it.
Or how about: write code that contains some dependency on exactly what exit
points are visible at the point where a dynamic non-local exit is
intercepted to execute some unwind-protect cleanup handlers.
Or apply a huge number of arguments to a function.