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