Casts

R

Richard Heathfield

jacob navia said:
Richard Heathfield wrote:


No they are not.

Yes, they are.
If the declaration of the temp is 76 lines before
you have to look it up,

If the declaration of the temp is 76 lines before, you need to refactor.
 
R

Richard Heathfield

jacob navia said:
Richard Heathfield wrote:

Note that my conversion was different:
int c = *((char *)p);

i.e. I am reading a byte from the void *;

I hadn't noticed that, actually. In that case, I'd use char c rather
than int c.
 
F

Flash Gordon

jacob navia wrote, On 23/06/07 22:53:
Keith Thompson wrote:


All expressions return a result object...

Not in C they don't. In C an object is a "region of data storage...".
> and that object is converted.
Conversions can only act in objects whose values are converted
isn't it?

No, conversions only apply to values in C.
Or are we getting into philosophy??? :)

No, the definition of the language.

I can accept not using the language of the C standard where it would
confuse a novice, but not using language in direct contradiction of the
C standard.
You are right.

I added:

Another case when casts are necessary occurs when passing arguments to a

How can it be "another case when casts are necessary" when the cases you
listed casts were not necessary?
variadic function. Since the type of the arguments can’t be known by the
compiler, it is necessary to cast a value to its exact expected type
(double to float for example),

Very bad example as the float will immediately be promoted back up to a
double before being passed to the variadic function.
> so that the arguments are converted to
the exact types the variadic function expects.

For instance

float f;

printf("%Lg\n",(long double)f);

The printf function expects a long double (format Lg). We need to
convert our float f into a long double to match the expectations of
printf.

That, however, is a case where it is needed but it is pointless since
you could just use the correct format specifier for a double instead.
Printing a pointer value would be a better example.
 
K

Keith Thompson

jacob navia said:
Keith Thompson wrote: [...]
The operand of a cast is an expression, not necessarily an object.

All expressions return a result object... and that object is converted.
Conversions can only act in objects whose values are converted
isn't it?

Or are we getting into philosophy??? :)

No, we're getting into the actual meanings of words.

Expression do not return objects; they yield values. Objects are not
converted; values are converted. Objects have values, but values are
not objects. In the expression

(int)1.5

*there is no object*. (Conceivably the compiler might store a
temporary value somewhere, but that's not an "object" in the C sense;
for example, it has no address.)

An "object" is a "region of data storage in the execution environment,
the contents of which can represent values" (C99 3.14).

[...]
I added:

Another case when casts are necessary occurs when passing arguments to
a variadic function. Since the type of the arguments can’t be known by
the compiler, it is necessary to cast a value to its exact expected
type (double to float for example), so that the arguments are
converted to the exact types the variadic function expects.

For instance

float f;

printf("%Lg\n",(long double)f);

The printf function expects a long double (format Lg). We need to
convert our float f into a long double to match the expectations of
printf.

That's not a great example. It would make much more sense to use the
"%g" format, which expects a double -- and a float argument is
promoted to double anyway. Or if you really wanted a long double, you
could declare f as a long double, and again, no cast is necessary.

I think an example involving integer types would illustrate the point
better. For example:

printf("sizeof obj = %lu\n", (unsigned long)sizeof obj);

where sizeof obj is of type size_t. (C99 provides the "%zu" format,
which does expect a size_t, but it's not universally supported.)
 
K

Keith Thompson

Richard Heathfield said:
jacob navia said:

I hadn't noticed that, actually. In that case, I'd use char c rather
than int c.

I'd probably use unsigned char, unless there's a specific reason to
use char.
 
K

Keith Thompson

jacob navia said:
Yes, the example was wrong.

Maybe this speaks against casts, but they are part of the language
and I have to treat that part isn't it?

I am not promoting casts for optimizations, I just wanted some
example for a cast usage, and I did not find anything better. By
changing the /= to += I hope I fixed the example, even if it is
not a very good one.

If it's not a very good example, even after you "fix" it, I suggest
you just drop it. We've been discussing cases where casts are
actually necessary and appropriate.

Casts can also be useful in controlling how numeric expressions are
evaluated (though it's always possible to rearrange the code to avoid
casts).
 
J

jacob navia

Keith said:
If it's not a very good example, even after you "fix" it, I suggest
you just drop it. We've been discussing cases where casts are
actually necessary and appropriate.

OK, you are right. Will drop it.
 
J

jacob navia

Flash said:
jacob navia wrote, On 23/06/07 22:53:

Not in C they don't. In C an object is a "region of data storage...".


No, conversions only apply to values in C.


No, the definition of the language.

I can accept not using the language of the C standard where it would
confuse a novice, but not using language in direct contradiction of the
C standard.


How can it be "another case when casts are necessary" when the cases you
listed casts were not necessary?


Very bad example as the float will immediately be promoted back up to a
double before being passed to the variadic function.

Not in lcc-win32
Not in MSVC
Not in gcc

Can you give me an example?

I bet you will have problems since if you are correct it would be
IMPOSSIBLE to pass a long double to a variadic function...
That, however, is a case where it is needed but it is pointless since
you could just use the correct format specifier for a double instead.
Printing a pointer value would be a better example.

We have %p to print pointers...

Anyway, is just an example. It doesn't have to be very clever, but just
illustrate a point


Thanks for your input

jacob
 
H

Harald van =?UTF-8?B?RMSzaw==?=

jacob said:
Not in lcc-win32
Not in MSVC
Not in gcc

Can you give me an example?

If your compiler does not perform the default promotions on variadic
function arguments, your compiler is broken. GCC very clearly does perform
the promotions:

#include <stdio.h>
#include <stdarg.h>
void f(int unused, ...) {
va_list ap;
va_start(ap, unused);
if (0) printf("%f\n", va_arg(ap, float));
if (1) printf("%f\n", va_arg(ap, double));
va_end(ap);
}
int main(void) {
f(0, 1.0f);
}

test.c: In function ‘f’:
test.c:6: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’
test.c:6: warning: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)
test.c:6: note: if this code is reached, the program will abort
I bet you will have problems since if you are correct it would be
IMPOSSIBLE to pass a long double to a variadic function...

What? So float is promoted to double. Where did anyone claim that long
double is also demoted to double?
We have %p to print pointers...

And you need a cast to portably print a non-void pointer value using %p...
 
P

pete

jacob navia wrote:
I am not promoting casts for optimizations, I just wanted some
example for a cast usage, and I did not find anything better.

double sort_time(/* It's just snippets */)
{
clock_t start, stop;

return (double)(stop - start) / (double)CLOCKS_PER_SEC;
}

clock_t is an implementation defined arithmetic type.
One cast prevents integer division;
two casts prevent long double division,
which is a microoptimization.
 
C

CBFalconer

Richard said:
jacob navia said:
.... snip ...


I can't think of a single good reason for casting a void * to a
char *.

Then how can you build a malloc system? :)
 
C

CBFalconer

jacob said:
.... snip ...

When not to use casts

Casts, as any other of the constructs above, can be misused. In
general, they make almost impossible to follow the type hierarchy
automatically. C is weakly typed, and most of the “weakness” comes
from casts expressions.

You are missing the golden rule - NEVER use a cast to suppress a
compiler error report. At the same time, most casts are
unnecessary.

A second general rule is that variadic functions REQUIRE casts of
their non-int (or non-void*) arguments.
 
R

Richard Heathfield

CBFalconer said:
Then how can you build a malloc system? :)

Why would you need to cast a void * to a char * to build a malloc
system? What's wrong with the guaranteed implicit conversion?
 
B

Barry

jacob navia said:
Hi

I am still writing my tutorial book about C. Here is the section about
casts. I would be interested in your opinions about this. Some people
have definite views about this subject ("never use casts") some others
(like me) are more "liberal" in this subject. I would be interested
in any feedback.

jacob

The thought that you would actually have anything to say about C is
funny. The idea that someone would read it, and take it seriously,
is just plain scary.
,
 
K

Keith Thompson

jacob navia said:
Flash Gordon wrote: [...]
Very bad example as the float will immediately be promoted back up
to a double before being passed to the variadic function.

Not in lcc-win32
Not in MSVC
Not in gcc

Can you give me an example?

I bet you will have problems since if you are correct it would be
IMPOSSIBLE to pass a long double to a variadic function...

I think you misunderstood.

When passed to a variadic function, an argument of type float is
promoted to double. (A double argument remains double, and a long
double argument remains long double.) Your example:

float f;
/* ... */
printf("%Lg\n",(long double)f);

isn't incorrect (the cast means that the argument is of type long
double), but it's confusing, since the cast is unnecessary *if* you
adjust the format:

float f;
/* ... */
printf("%g\n", f);

and the fact that float arguments are promoted to double just confuses
the issue.

[...]
We have %p to print pointers...

We have %p to print pointers of type void*. (It should also work with
char*, but IMHO it's a bad idea to depend on that.) For example:

int i;
printf("&i = %p\n", (void*)&i);

Yes, the cast is necessary.
 
K

Keith Thompson

CBFalconer said:
A second general rule is that variadic functions REQUIRE casts of
their non-int (or non-void*) arguments.

It's not that simple. Even for printf, no cast is required for
arguments of type double, long double, all integer types at least as
wide as int, or char*. A variadic function other than printf can take
arguments of any arbitrary type.

The point is that the compiler doesn't have enough information to
perform the implicit conversions that are done for non-variadic
arguments (when a prototype is visible).
 
J

jacob navia

pete said:
double sort_time(/* It's just snippets */)
{
clock_t start, stop;

return (double)(stop - start) / (double)CLOCKS_PER_SEC;
}

clock_t is an implementation defined arithmetic type.
One cast prevents integer division;
two casts prevent long double division,
which is a microoptimization.

Thanks. I added this:
Another use of casts is to avoid integer division:

int a,b;
double c;
....
c = a/b; // Invokes integer division.
c = a/(double)b; // Invokes floating point division.
 
R

Richard Heathfield

Keith Thompson said:
We have %p to print pointers of type void*. (It should also work with
char*, but IMHO it's a bad idea to depend on that.) For example:

int i;
printf("&i = %p\n", (void*)&i);

Yes, the cast is necessary.

Like most (all?) casts, this one /can/ be avoided, in this case by using
a temp, but I have to say it's probably not worth it for a printf.
 
M

Malcolm McLean

Barry said:
The thought that you would actually have anything to say about C is
funny. The idea that someone would read it, and take it seriously,
is just plain scary.
I've never written a C compiler. I've written a BASIC interpreter which
semi-compiles on the fly, and I can tell you that was difficult enough. Have
you? Jacob Navia has.
 
R

Richard Heathfield

Malcolm McLean said:
The thought that [Mr Navia] would actually have anything to say about
C is funny. The idea that someone would read it, and take it
seriously, is just plain scary.
I've never written a C compiler. I've written a BASIC interpreter
which semi-compiles on the fly, and I can tell you that was difficult
enough. Have you? Jacob Navia has.

No, he has not. He has taken an existing compiler, and tweaked bits of
it occasionally. Over the years and indeed right up to the last few
messages he's posted in clc, Mr Navia has showed himself to be so
ignorant of C that I find it astonishing that he manages to maintain
lcc-win32 without breaking it (if, indeed, he hasn't broken it
already).

For example, in the first article in this very thread he has shown that
he doesn't even know what a cast does.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Pointer casts for OOP 2
function casts 27
Casts on lvalues 74
Union and pointer casts? 13
Better casts? 10
casts and pointers 0
cast musings 19
Casts for srand? (FAQ 13.17) 2

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top