From: Alessio Stalla on
On Dec 16, 11:44 am, Donkey Hottie <don...(a)fred.pp.fi> wrote:
> On 15.12.2009 19:55, markspace wrote:
>
> > Here's a little issue from my code that bugging me right now.  I have a
> > generic class that implements Callable<Void>
>
> > However this makes me suspicious that there's a hidden cast in
> > there now, and I'd prefer not to do that because the algorithm is very
> > time critical.
>
> Is a cast somehow a runtime operation? In C it used to be a compile time
> operation, and does not add any runtime penalty. A warning will be
> issued, but any extra code hardly will be generated. I may be wrong with
> Java, though.

In Java a cast is a runtime operation because it implies a runtime
type check. In C a cast is merely a "promise" by the programmer to the
compiler that a certain datum is of a certain type, so if the
programmer makes a mistake no error is signaled and things break
horribly. (some casts in C and Java are actually type conversions,
e.g. from int to long).

Alessio

From: Eric Sosman on
On 12/16/2009 6:58 AM, Alessio Stalla wrote:
> On Dec 16, 11:44 am, Donkey Hottie<don...(a)fred.pp.fi> wrote:
>> On 15.12.2009 19:55, markspace wrote:
>>
>>> Here's a little issue from my code that bugging me right now. I have a
>>> generic class that implements Callable<Void>
>>
>>> However this makes me suspicious that there's a hidden cast in
>>> there now, and I'd prefer not to do that because the algorithm is very
>>> time critical.
>>
>> Is a cast somehow a runtime operation? In C it used to be a compile time
>> operation, and does not add any runtime penalty. A warning will be
>> issued, but any extra code hardly will be generated. I may be wrong with
>> Java, though.
>
> In Java a cast is a runtime operation because it implies a runtime
> type check.

Right, except (as you mentioned later) that sometimes the
run-time action is a conversion, not a type check. I imagine
that some nearly-vacuous casts like `(int)42' or `(Object)"Hello"'
might have no run-time image at all.

> In C a cast is merely a "promise" by the programmer to the
> compiler that a certain datum is of a certain type,

Wrong, but the wrongness isn't especially topical for a
Java forum. C's casts -- *all* C's casts -- are conversions
(some may be vacuous).

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: Alessio Stalla on
On Dec 16, 2:07 pm, Eric Sosman <esos...(a)ieee-dot-org.invalid> wrote:
> On 12/16/2009 6:58 AM, Alessio Stalla wrote:
> > In C a cast is merely a "promise" by the programmer to the
> > compiler that a certain datum is of a certain type,
>
>      Wrong, but the wrongness isn't especially topical for a
> Java forum.  C's casts -- *all* C's casts -- are conversions
> (some may be vacuous).

I'm going completely off topic now, but I'm curious. I know C only
superficially, and I can't understand what you said. How is, e.g.,
struct something* castPtr = (struct something*) ptr; a conversion?
Doesn't this just say to the compiler that 'castPtr' points to a
struct something, so when it will generate code for, say, castPtr-
>someField, it should dereference castPtr + an offset of, say, 42 to
access someField?

Alessio
From: Thomas Pornin on
According to Alessio Stalla <alessiostalla(a)gmail.com>:
> I'm going completely off topic now, but I'm curious. I know C only
> superficially, and I can't understand what you said.

The C standard allows pointers of distinct types to have distinct
in-memory representations. For instance, this is not valid C:

char *fake_cast_wrong(int *x)
{
char *y;

memcpy(&y, &x, sizeof x);
return y;
}

because this code tries to interpret the memory representation of 'x' (a
pointer to int) as the memory representation of a pointer to char,
without using a cast. For that matter, the memory representation of a
pointer to char may have a different length than the memory
representation of a pointer to int, so the code above could be a devious
example of a buffer overflow.

Such architectures are now quite rare(*). In most current systems which
support C compilation, all pointers have the same uniform in-memory
representation, and casts between pointer types occur no runtime cost:
the C compiler does not have to generate any conversion code since the
conversion turns out to be a no-operation.

In Java you do not have access to the in-memory representation; whether
some kind of references have a distinct representation is private
business to the JVM. Most JVM prefer a uniform in-memory representation
because it is easier and faster. However, a cast in Java usually implies
a runtime type check, which the C standard does not mandate (the C
standard does not _forbid_ runtime type checks, it even allows the
program to loudly complain in case of a "wrong cast", but it does not
mandates anything and most C compilers perform no runtime check). In
Java, if the cast leads to an incompatible type, then the JVM _must_
issue a ClassCastException. Therefore, casts in Java tend to be somewhat
more expensive than casts in C. On the other hand, casts between
reference types should be rare in a properly structured OO code.


--Thomas Pornin

(*) Old architectures never die, they just become cheaper, and therefore
more common. However, it is probable that the DSP which have
legal-but-weird constraints on C code are rarely programmed in C.
From: Eric Sosman on
On 12/16/2009 9:17 AM, Alessio Stalla wrote:
> On Dec 16, 2:07 pm, Eric Sosman<esos...(a)ieee-dot-org.invalid> wrote:
>> On 12/16/2009 6:58 AM, Alessio Stalla wrote:
>>> In C a cast is merely a "promise" by the programmer to the
>>> compiler that a certain datum is of a certain type,
>>
>> Wrong, but the wrongness isn't especially topical for a
>> Java forum. C's casts -- *all* C's casts -- are conversions
>> (some may be vacuous).
>
> I'm going completely off topic now, but I'm curious. I know C only
> superficially, and I can't understand what you said. How is, e.g.,
> struct something* castPtr = (struct something*) ptr; a conversion?

It converts the value of `ptr' from whatever `ptr's type
is to the new type `struct something *'. On many systems it
happens that all data pointers have the same representation,
so the converted value is bit-for-bit the same as the original
(if `ptr' was in fact a pointer). But on some systems --
word-addressed systems, especially -- different pointer types
have different representations and sometimes even different sizes,
and the conversion actually stirs the bits around.

Example #1: C doesn't nail down the ranges of its primitive
types as tightly as Java does, with the result that `long' and
`int' sometimes share the same range and representation; they're
just different names for the same underlying "machine thing."
Yet `(long)42' is still a conversion of the value 42 from `int'
to `long' -- and on a machine where `int' and `long' are *not*
the same, the conversion actually supplies new bits that the
original value didn't have. Either way, it's a conversion of
a value from one type to another, whether the representation
changes or not.

Example #2: `(double)42' converts the value 42 from `int'
to `double', which almost certainly scrambles the bits even
though it preserves the numerical value. The cast does not say
"Just pretend the bits of the `int' constant 42 are the bits
of a `double' object." (For one thing, it's quite likely that
an `int' object has too few bits to make a `double', so "just
pretend" would be doomed from the outset.)

> Doesn't this just say to the compiler that 'castPtr' points to a
> struct something, so when it will generate code for, say, castPtr-
>> someField, it should dereference castPtr + an offset of, say, 42 to
> access someField?

The part that says `castPtr' points to a `struct something'
is not the cast operator, but the declaration of `castPtr' itself.
`struct something * castPtr;', even with no initialization at all,
says that much. The initialization provides a value, and the cast
operator in the initializing expression makes sure that the value
is of type `struct something *' by converting its operand's value
from whatever the operand's own type was.

Followups set to comp.lang.c, because we're really not
talking about Java any more.

--
Eric Sosman
esosman(a)ieee-dot-org.invalid