Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Down-casting integer

69 views
Skip to first unread message

Vijay Mathew

unread,
Oct 6, 2012, 3:40:13 AM10/6/12
to
I want to translate the following C code to Common Lisp:

int main()
{
char a = 255;
char b = 244;
char c = (a << 8) | b;
printf ("%d\n", c); // => -12
}

I tried this:

(logior (ash 255 8) 244) ;; => 65524

The values are treated as integers. How can I get `logior` and `ash` to treat their arguments as bytes and get the same result produced by the C code?

Best regards,

--Vijay

Nils M Holm

unread,
Oct 6, 2012, 3:52:24 AM10/6/12
to
(let ((x (mod (logior (ash 255 8) 244) 256)))
(if (> x 127)
(- 256 x)
x))

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Kaz Kylheku

unread,
Oct 6, 2012, 4:07:36 AM10/6/12
to
On 2012-10-06, Vijay Mathew <vijay.th...@gmail.com> wrote:
> I want to translate the following C code to Common Lisp:
>
> int main()
> {
> char a = 255;

Not sure how an "implementation-defined conversion" translates to Common Lisp.
Char may be only 8 bits wide, and it may be signed, so that it only
goes up to 127.

> char b = 244;
> char c = (a << 8) | b;

Shifting a 1 bit into the sign bit of a signed type is undefined behavior.

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
behavior.

> printf ("%d\n", c); // => -12

So this result is basically nonportable garbage.

> }
>
> I tried this:
>
> (logior (ash 255 8) 244) ;; => 65524

Whereas this is mathematically correct.

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.

Vijay Mathew

unread,
Oct 6, 2012, 4:39:11 AM10/6/12
to
`char` is assumed to be 8-bits wide. The solution of Nils seems to be what I need.

Thanks for helping me out.

--Vijay

Pascal J. Bourguignon

unread,
Oct 6, 2012, 5:41:14 AM10/6/12
to
Vijay Mathew <vijay.th...@gmail.com> writes:

> `char` is assumed to be 8-bits wide. The solution of Nils seems to be what I need.

You didn't understand C.

char may be 8 bits wide, your C code is still undefined, while the given
lisp code is perfect defined and sound. And most C implementations
defined char as signed, so already char a = 255; is undefined.

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
0 new messages