c prog -plz explain

K

Kaz Kylheku

SAHIL MAHLA wrote: ...
It's because we are typecasting i's address into a double* and [...]
You are "casting", not "typecasting".

For the record, I sometimes say "typecast" too. Picked it up 25 years
ago or so, probably from my teachers. I'm tempted to suggest that it
should be tolerated as a nickname ...

Casting is the situation of actors being put into roles.

Typecasting is when certain actors keep getting certain kinds of roles.
(Always the bad guy, or the token representative of an ethnic group, etc.)

Maybe this can be worked into some kind of kind of parallel in C usage.

Discuss among yourselves ...
 
N

Noob

Kaz said:
C is a strongly typed language. It has the concept of type: that an operation
of the correct type must be applied to a datum for well-defined behavior. C has
considerable translation-time type checking in it to support its type system,
but when you use casts, especially for conversions among pointer types, you can
defeat the type system and write programs which break the rules, but do not
produce any diagnostics when compiled, and even make an executable.

Ergo, a simple rule for beginners would be: "Don't use casts anywhere".

There are very few valid reasons for using casts.

One is passing NULL to a variadic function (e.g. execl)

Another is trying to define APIs with generic parameters (e.g. connect)
i.e. the poor man's polymorphism.

Regards.
 
K

Kenny McCormack

Jorgen Grahn said:
SAHIL MAHLA wrote: ...
It's because we are typecasting i's address into a double* and [...]
You are "casting", not "typecasting".

For the record, I sometimes say "typecast" too. Picked it up 25 years
ago or so, probably from my teachers. I'm tempted to suggest that it
should be tolerated as a nickname ...

/Jorgen

And so do 99% of programmers.

Yeah, but not in this Establishment...

--
"Although written many years ago, Lady Chatterley's Lover has just
been reissued by the Grove Press, and this fictional account of the
day-to-day life of an English gamekeeper is still of considerable
interest to outdoor minded readers, as it contains many passages on
pheasant raising, the apprehending of poachers, ways to control vermin,
and other chores and duties of the professional gamekeeper.

"Unfortunately, one is obliged to wade through many pages of extraneous
material in order to discover and savor these sidelights on the
management of a Midlands shooting estate, and in this reviewer's opinion
this book cannot take the place of J.R. Miller's Practical Gamekeeping"
(Ed Zern, Field and Stream, November 1959, p. 142).
 
K

Kaz Kylheku

Ergo, a simple rule for beginners would be: "Don't use casts anywhere".
There are very few valid reasons for using casts.

One is passing NULL to a variadic function (e.g. execl)

Another is trying to define APIs with generic parameters (e.g. connect)
i.e. the poor man's polymorphism.

What if you're calculating i / j, where i and j are integers, and you
want an answer like 2.75?

No i / (double) j for you; stick with two? :)

The stupid thing is that completely bat-shit unsafe stuff shares the same
notation with necessary conversions.
 
L

Lowell Gilbert

Kaz Kylheku said:
SAHIL MAHLA wrote: ...
It's because we are typecasting i's address into a double* and [...]
You are "casting", not "typecasting".

For the record, I sometimes say "typecast" too. Picked it up 25 years
ago or so, probably from my teachers. I'm tempted to suggest that it
should be tolerated as a nickname ...

Casting is the situation of actors being put into roles.

Typecasting is when certain actors keep getting certain kinds of roles.
(Always the bad guy, or the token representative of an ethnic group, etc.)

Maybe this can be worked into some kind of kind of parallel in C usage.

Type refers to the metal objects used in mechanical printing.
Type casting is the use of molds and molten metal to produce such objects.
 
N

Noob

I realize now that I only considered "pointer" casts.
What if you're calculating i / j, where i and j are integers, and you
want an answer like 2.75?

No i / (double) j for you; stick with two? :)

Doh!

One trying to abide by the aforementioned "simple rule" could rely
on implicit conversion, as in

double d_i = i, d_j = j, res = d_i / d_j;

But I do see your point.
Perhaps the rule should be "Don't use pointer casts anywhere"
The stupid thing is that completely bat-shit unsafe stuff shares the same
notation with necessary conversions.

Do you have other examples of reasonable use of casts?

Regards.
 
K

Kaz Kylheku

Jorgen Grahn said:
...
It's because we are typecasting i's address into a double* and [...]

You are "casting", not "typecasting".

For the record, I sometimes say "typecast" too. Picked it up 25 years
ago or so, probably from my teachers. I'm tempted to suggest that it
should be tolerated as a nickname ...

/Jorgen

And so do 99% of programmers.

Yeah, but not in this Establishment...

I've been here since 1995, which makes me the Establishment; not these
barking newcomers.

You may use "typecast" as a synonym for "cast". Also "explicit cast" is fine,
even though there is no "implicit cast".

If anyone corrects you on this, and wasn't seen here before Y2K, you can safely
tell them to **** the hell off, with my full support.

(I would somewhat prefer that conversions that are not explicitly requested
not be called casts. At least think about it a little, but it's your call.
Do unions cast? You decide.)

I also propose that "typecast" be used specifically when a value is being
reinterpreted (type punned): that is to say, a pointer to that type is being
cast, and the object itself (which wasn't subject to the cast notation) is
being typecast. (If unions do cast, they definitely typecast.)

I.e. i / (double) j is a cast, (bar_struct *) &foo_struct_obj is a typecast.
The pointer is cast; what is typecast is foo_struct_obj itself (whose value
is not even being accessed, let alone converted, in the cast).

Example sentence: "In this area of the code, foo_struct_obj {is/has been}
typecast {to/as a} bar_struct".
 
E

Eric Sosman

Kaz said:
[...]
Ergo, a simple rule for beginners would be: "Don't use casts anywhere".
There are very few valid reasons for using casts.

I realize now that I only considered "pointer" casts.
[...]
Perhaps the rule should be "Don't use pointer casts anywhere"
[...]
Do you have other examples of reasonable use of casts?

How about converting between a struct pointer and a pointer
to the struct's first element? Or using a struct pointer and
a byte offset to get to an element of the struct? (Both of these
might be considered beyond the "beginner" boundary.)

How about implementing a comparator function for qsort() or
bsearch()? Personally, I prefer to introduce a couple helper
variables:

int compare(const void *pp, const void *qq) {
const struct whatnot *p = pp, *q = qq;
return strcmp(p->name, q->name);
}

.... but doing without the extra variables and applying casts
to the arguments would be perfectly reasonable.

Since there's no analog to `void*' for function pointers,
casts are often necessary when dealing with pointers to functions
of dissimilar types. (Beyond beginner boundary?)
 
J

James Kuyper

On 3/12/2014 10:56 AM, Noob wrote: ....
I realize now that I only considered "pointer" casts.
[...]
Perhaps the rule should be "Don't use pointer casts anywhere"
[...]
Do you have other examples of reasonable use of casts?

How about converting between a struct pointer and a pointer
to the struct's first element?

In one direction, there's a perfectly safe alternative:
&struct_pointer->first_member (unless the struct has an opaque type -
but it really shouldn't have an opaque type in any code that is going to
try to access it's members). It's only going in the other direction that
requires a cast.
How about implementing a comparator function for qsort() or
bsearch()? Personally, I prefer to introduce a couple helper
variables:

int compare(const void *pp, const void *qq) {
const struct whatnot *p = pp, *q = qq;
return strcmp(p->name, q->name);
}

... but doing without the extra variables and applying casts
to the arguments would be perfectly reasonable.

Because I prefer to treat casts as danger signs, I also prefer using the
the helper variables.
 
K

Ken Brody

On 3/12/2014 3:40 AM, Kaz Kylheku wrote:
[...]
Casting is the situation of actors being put into roles.

Typecasting is when certain actors keep getting certain kinds of roles.
(Always the bad guy, or the token representative of an ethnic group, etc.)

Maybe this can be worked into some kind of kind of parallel in C usage.

float i,j;

[...]
 
G

glen herrmannsfeldt

Noob said:
Kaz Kylheku wrote:
Ergo, a simple rule for beginners would be: "Don't use casts anywhere".

There are enough uses for non-pointer casts that I wouldn't rule
them out for beginners, but no good reasons that I can think of
for pointer casts.

-- glen
 
G

glen herrmannsfeldt

Kaz Kylheku said:
(snip)
(snip)

What if you're calculating i / j, where i and j are integers, and you
want an answer like 2.75?
No i / (double) j for you; stick with two? :)
The stupid thing is that completely bat-shit unsafe stuff shares
the same notation with necessary conversions.

Well, first, I agree, but sometimes there are ways around it.

If you want percentage, you can:

pct=100.*i/j;

no cast needed, because the multiply will force the conversion.

Also, sometimes in the case where I want i/j not to be integer,
it turns out to make more sense for i and/or j to be double.

Also, often when I have i and j, I don't want i/j to be integer
but i*(large_integer)/j to be integer. Conveniently, most processors
allow for this. Inconveniently, C doesn't.

-- glen
 
J

James Kuyper

On 03/12/2014 03:03 PM, glen herrmannsfeldt wrote:
....
There are enough uses for non-pointer casts that I wouldn't rule
them out for beginners, but no good reasons that I can think of
for pointer casts.

So, would you write code like the following, to avoid casts?

double x;
void *temp = &x;
printf("%p\n", temp);


Imagine that a third party library declares

int third_party_func(char*);

even though third_party_func() doesn't write through the char* pointer,
it only reads from it. You don't have the influence needed to convince
them to use "const char*" instead. Your own code has:

const char *message = "This memory cannot be safely modified";

How do you pass message to third_party_func()?
 
E

Eric Sosman

Well, first, I agree, but sometimes there are ways around it.

If you want percentage, you can:

pct=100.*i/j;

no cast needed, because the multiply will force the conversion.

ObPuzzle: Which of the `return' statements below is the best,
and why?

#include <time.h>
/**
* Find how many CPU seconds were consumed between
* two values returned by clock().
*/
double cpuSeconds(clock_t t0, clock_t t1) {
/* A */ return (t1 - t0) / CLOCKS_PER_SEC;
/* B */ return (t1 - t0) / (double) CLOCKS_PER_SEC;
/* C */ return (t1 - t0) / (CLOCKS_PER_SEC + 0.0);
}
 
J

James Kuyper

On 03/12/2014 04:05 PM, Eric Sosman wrote:
....
ObPuzzle: Which of the `return' statements below is the best,
and why?

#include <time.h>
/**
* Find how many CPU seconds were consumed between
* two values returned by clock().
*/
double cpuSeconds(clock_t t0, clock_t t1) {
/* A */ return (t1 - t0) / CLOCKS_PER_SEC;
/* B */ return (t1 - t0) / (double) CLOCKS_PER_SEC;
/* C */ return (t1 - t0) / (CLOCKS_PER_SEC + 0.0);
}

Option A can't return fractions of a second if clock_t is an integer
type, so I wouldn't choose that. Also, it rounds fractional parts toward
0, whereas I prefer rounding to negative infinity.

If clock_t is long double, option B unnecessarily discards precision in
CLOCKS_PER_SEC, whereas option C unnecessarily discards precision in the
final result. I think that carrying out the actual calculation in long
double is slightly preferable, which favors C over B, but it's not a
strong preference.

I'd define cpuSeconds as returning long double, which would imply a
corresponding re-write of option B. With that re-write, I'd favor B as
the clearest of the two versions that deals correctly with the
possibility that clock_t is an integer type.
 
I

Ian Collins

Eric said:
ObPuzzle: Which of the `return' statements below is the best,
and why?

#include <time.h>
/**
* Find how many CPU seconds were consumed between
* two values returned by clock().
*/
double cpuSeconds(clock_t t0, clock_t t1) {
/* A */ return (t1 - t0) / CLOCKS_PER_SEC;
/* B */ return (t1 - t0) / (double) CLOCKS_PER_SEC;
/* C */ return (t1 - t0) / (CLOCKS_PER_SEC + 0.0);
}

Or Option D

double cpuSeconds(clock_t t0, clock_t t1) {
static const double clocksPerSec = CLOCKS_PER_SEC;
return (t1 - t0) / clocksPerSec;
}
 
K

Kaz Kylheku

On 03/12/2014 03:03 PM, glen herrmannsfeldt wrote:
...

So, would you write code like the following, to avoid casts?

double x;
void *temp = &x;
printf("%p\n", temp);

I would and I do. In the TXR language project, I banned void *. Generic
pointers to anything are mem_t *, and those require casts in either direction.
The chk_malloc function that is used everywhre returns mem_t *, and various
other situations.

Other than that, there is no value in being able to express a potentially
unsafe pointer conversion without using the cast syntax, and it is wrongheaded
to look for the ability to do such a thing for the sake of saving keystrokes.

This is basically the same attitude which also does not want to write comments,
or documentation.

A cast is a remark that you put in the code that something very noteworthy is
going on that, if bungled, could wreck the correctness of the the program, in
exchange for the compiler making it happen without a diagnostic. That remark
has a particular syntax, and that syntax can be found by automatic means.

A tool that parses C can be developed which makes a report of all file names
and line numbers where pointer casts occur. Regular expression grepping can
almost do it, except if it is concealed by macrology.

In other words, you're not getting rid of the diagnostic: you're just removing
the diagnostic from the compiler output, and placing an altered representation
of it into the code in the form of a type in parentheses. The cast is a
diagnostic label embedded in the code. It ensures that something is written
somewhere, addressing itself to the questionable situation.
Imagine that a third party library declares

int third_party_func(char*);

even though third_party_func() doesn't write through the char* pointer,
it only reads from it. You don't have the influence needed to convince
them to use "const char*" instead. Your own code has:

const char *message = "This memory cannot be safely modified";

How do you pass message to third_party_func()?

If you write in Clean C (code that compiles as either C or C++)
you can do this:

#ifdef __cplusplus
#define REMOVE_QUAL(TYPE, PTR) (const_cast<TYPE>(PTR))
#else
#define REMOVE_QUAL(TYPE, PTR) ((TYPE) (PTR))
#endif

third_party_func(REMOVE_QUAL(char *, my_const_string));

Suppose my_const_string is wchar_t *. It will still compile as C,
but you will catch it when you compile as C++.
 
I

Ian Collins

Kaz said:
Other than that, there is no value in being able to express a potentially
unsafe pointer conversion without using the cast syntax, and it is wrongheaded
to look for the ability to do such a thing for the sake of saving keystrokes.

This is basically the same attitude which also does not want to write comments,
or documentation.

A cast is a remark that you put in the code that something very noteworthy is
going on that, if bungled, could wreck the correctness of the the program, in
exchange for the compiler making it happen without a diagnostic. That remark
has a particular syntax, and that syntax can be found by automatic means.

One of the good reasons for adding the wordy casts to C++ which would
make them a useful addition to C. Having to write nested casts to
remove a qualifier and change a type is a good hint to developer to
think twice about what they are doing and the reader that something out
of the ordinary is happening.
 
T

Tim Rentsch

Eric Sosman said:
ObPuzzle: Which of the `return' statements below is the best,
and why?

#include <time.h>
/**
* Find how many CPU seconds were consumed between
* two values returned by clock().
*/
double cpuSeconds(clock_t t0, clock_t t1) {
/* A */ return (t1 - t0) / CLOCKS_PER_SEC;
/* B */ return (t1 - t0) / (double) CLOCKS_PER_SEC;
/* C */ return (t1 - t0) / (CLOCKS_PER_SEC + 0.0);
}

I offer without further comment a fourth alternative:

return (0 ? cpuSeconds(t0,t1) : t1-t0) / CLOCKS_PER_SEC;
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top