Casts

J

jacob navia

Mark said:
<mode=sarcastic>
Oh, I thought he was writing a /tutorial/ - you know, for beginners...
</mode>

They are beginners BEFORE reading the tutorial.
Afterwards they are not, at least I hope.

I have explained with much detail quite complicated constructs, for instance
function pointer syntax, qsort callback prototypes, and other goodies.
Exposing beginners to
int c = *((char *)p);
is advanced but not really beyond the scope of a tutorial.
 
R

Richard Tobin

Seems pretty clear to me.
[/QUOTE]
<mode=sarcastic>
Oh, I thought he was writing a /tutorial/ - you know, for beginners...
</mode>

Ha ha. We were discussing whether it was a clear idiom, not whether
beginners would already know what it meant. You just seem to be
looking for something to denounce.

-- Richard
 
C

Chris Torek

[On using casts vs using temporary variables]

Clarity of purpose is one important item.

Another, admittedly minor, problem is that assignment introduces an
alias - two variables pointing to the same memory. Other things being
equal, that is undesirable.

I think this is not exactly "minor" either.

Code generally has two functions:

- It should be an unambiguous set of directions to a computer, and

- It should provide sufficient clues to later programmers (who
may be the original code-writers, or others) so that they can
understand not only *what* is to be done but *why* it is being
done.

My own take on casts vs temporaries is a specialization of a more
general rule:

If something is important, give it a *name*. If it is going
to be used frequently, give it a name. If it is unimportant
*and* will appear rarely (especially "just once"), try *not*
to give it a name.

Casts create temporary values but do not give them names -- so
they should be avoided if you will use the result more than once.
Hence, in a typical qsort comparison function, where we need to
use the arguments several times, we should avoid casts. The
arguments arrive with the "wrong" type, so we must create pointer
aliases, despite their drawbacks.

/*
* Compare XYZs for qsort. Returns 0 if the left and right
* side XYZs are equal, -1 if the left XYZ is "less than"
* the right XYZ, and 1 if the left XYZ is "greater than" the
* the right.
*/
int xyz_compare(const void *l0, const void *r0) {
const struct xyz *l = l0;
const struct xyz *r = r0;

if (l->firstkey != r->firstkey)
return l->firstkey < r->firstkey ? -1 : 1;
if (l->secondkey != r->secondkey)
return l->secondkey < r->secondkey ? -1 : 1;
...
return 0;
}

To emphasize the fact that "l" and "r" (left and right) are
the "real" arguments, and the parameters simply come in with
the "wrong" type (void *), the parameters are named "l0" and
"r0" and the function "strips off the zeros" when converting
the arguments to the correct type.

I also tend to use this "x sub zero" notation for preserving
arguments that will be modified inside the function: x0 is the
original (input) value of x, which is then changed as needed, with
the original value still available as needed. This provides the
relation between the variables (both are "x") as well as the
"sequence" aspect: x sub 0 is the original, x sub i is the i'th if
we have to preserve additional values, and x is the current one if
we want a short name for it. (In another language this might be
bad since "x" could refer to the entire vector, but C is not APL. :) )
 
O

Old Wolf

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

If you are calling a variadic function that specifies
its end-of-argument-list marker as (char *)NULL
 
C

CBFalconer

Chris said:
.... snip ...

/*
* Compare XYZs for qsort. Returns 0 if the left and right
* side XYZs are equal, -1 if the left XYZ is "less than"
* the right XYZ, and 1 if the left XYZ is "greater than" the
* the right.
*/
int xyz_compare(const void *l0, const void *r0) {
const struct xyz *l = l0;
const struct xyz *r = r0;

if (l->firstkey != r->firstkey)
return l->firstkey < r->firstkey ? -1 : 1;
if (l->secondkey != r->secondkey)
return l->secondkey < r->secondkey ? -1 : 1;
...
return 0;
}

To emphasize the fact that "l" and "r" (left and right) are
the "real" arguments, and the parameters simply come in with
the "wrong" type (void *), the parameters are named "l0" and
"r0" and the function "strips off the zeros" when converting
the arguments to the correct type.

However you have created the easily misread variable l0, often
indistinguishable from ten. To avoid this, consider using lt and
rt in the names.
 
R

Richard Heathfield

jacob navia said:

int c = *((char *)p);

You read that c is assigned the value of p treated as a char *.
Period. Immediately visible.

And wrong. What you say it does isn't what it actually does. Well, not
in C, anyway. I can't answer for the bizarre language you seem to have
constructed for yourself and your users.
 
R

Richard Heathfield

Old Wolf said:
If you are calling a variadic function that specifies
its end-of-argument-list marker as (char *)NULL

Ah! Thanks. I'm pretty sure that was the exception at the back of my
mind, that was preventing me from making a more definite claim than
"there is *no* reason...", but I couldn't quite call it to mind.
 
R

Richard Tobin

I can't think of a single good reason for casting a void * to a char *.
[/QUOTE]
If you are calling a variadic function that specifies
its end-of-argument-list marker as (char *)NULL

I don't see much attraction in using NULL if you're going to cast it.
I would prefer "(char *)0". And of course NULL might not be defined
as "(void *)0".

How does the DS9K arrange for "(void *)0" not to work in this case?
Does it have separate areas for char * and void * arguments to
variadic functions?

-- Richard
 
R

Richard Tobin

How does the DS9K arrange for "(void *)0" not to work in this case?
Does it have separate areas for char * and void * arguments to
variadic functions?

Section 6.2.5 (Types) of C99 says that char * and void * have the same
representation and alignment requirements. Footnote 39 expains that
this is "meant to imply interchangeability as arguments to functions
[...]". The implementation suggested above obeys the normative text
but does not achieve the goal described in the footnote.

-- Richard
 
R

Richard Tobin

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.
[/QUOTE]
Am I missing something important here?
Why is the cast necessary in this case? We are, after all, only using
the pointer value, not what it points to.

Pointers to int and pointers to void may have quite different
representations, and may even have different sizes. They may
also be passed to variadic functions differently. If printf()
tries to retrieve a void * when the user passed an int *, anything
may happen.

-- Richard
 
J

Johan Bengtsson

Keith 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.
Am I missing something important here?
Why is the cast necessary in this case? We are, after all, only using
the pointer value, not what it points to.

confused...
 
R

Richard Heathfield

Johan Bengtsson said:
Am I missing something important here?
Why is the cast necessary in this case?

The Standard allows for the possibility that not all pointers have the
same size or representation. Rather than provide a different format
specifier for every single pointer type - an impossible task - C
requires that the pointer provided to match a %p conversion specifier
must be a pointer to void.
 
M

Mark McIntyre

Mark McIntyre wrote:

They are beginners BEFORE reading the tutorial.
Afterwards they are not, at least I hope.

Thats the plan! :)
I have explained with much detail quite complicated constructs, for instance
function pointer syntax, qsort callback prototypes, and other goodies.
Exposing beginners to
int c = *((char *)p);
is advanced but not really beyond the scope of a tutorial.

Fair enough.
In the context of this thread I found it just a little overcomplex but
that was just my impression.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

You just seem to be
looking for something to denounce.

No, I was quite serious that the purpose a= *((foo*)bar) seemed far
from clear to me, in the context of a tutorial.

However your comment above is denouncable, so thats deuce I think.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
J

jacob navia

Flash said:
Harald van Dijk wrote, On 24/06/07 00:21:



Thanks for saving me the trouble of arguing with Jacob, your rebuttal
was exactly in line with my thoughts when I posted :)

servile
Main Entry: ser·vile
Function: adjective
Etymology: Middle English, from Anglo-French servil, from Latin
servilis, from servus slave
1 : of or befitting a slave or a menial position
2 : meanly or cravenly submissive : ABJECT

http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=servility
 
F

Flash Gordon

jacob navia wrote, On 25/06/07 21:59:

<snip definition of servile>

Firstly, why don't you address the points raised rather than attacking
the people making them. It does not improve peoples opinion of you or,
to my knowledge, damage whatever reputations the people you attack have.

Secondly, what makes you think that either Harald or I is servile to the
other. Yes, I thanked him, but that is only polite, and I made it clear
that he had addressed your response to my post in a manner I agreed
with, thus saving me from making the points as well. Neither Harald nor
I behaved in a manner that most would consider servile.

Thirdly, what makes you think that you know the English language better
than an Englishman?
 
K

Keith Thompson

jacob navia said:
servile
Main Entry: ser·vile
Function: adjective
Etymology: Middle English, from Anglo-French servil, from Latin
servilis, from servus slave
1 : of or befitting a slave or a menial position
2 : meanly or cravenly submissive : ABJECT

http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=servility

Would you care to explain why you're giving us a definition for a word
that has absolutely nothing to do with the conversation?

Subtlety and sarcasm don't work for you, jacob. Your postings are
much better when you write straightforwardly, saying what you mean.
 
M

Mark L Pappin

CBFalconer said:
However you have created the easily misread variable l0, often
indistinguishable from ten. To avoid this, consider using lt and
rt in the names.

Or, use a font which distinguishes ells and ones, and ohs and zeros.
Or, use the name 'l_0' for "ell sub zero".

mlp
 
K

Keith Thompson

jacob navia said:
Richard said:
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.

This is a lie. I have rewritten everything in lcc-win32. I wrote
the assembler, the linker, the debugger, the IDE, the optimizer,
the lexer and syntax analysis, there is nothing from lcc but the name.

I have said this here many times but you go on telling stories.

I repeat: there is almost nothing left from lcc in lcc-win32.

Jacob, I mentioned earlier that I don't recall you make this claim
previously. I don't doubt your statement that lcc-win32 is a nearly
complete re-write of lcc, but I *do* doubt your claim that you've
mentioned this many times in this newsgroup.

Are you prepared to either (a) back up your claim with references to
articles you've posted here, or (b) apologize to Richard for
baselessly calling him a liar?
 
C

CBFalconer

.... snip, attribute left for context ...
Are you prepared to either (a) back up your claim with references
to articles you've posted here, or (b) apologize to Richard for
baselessly calling him a liar?

What we need here is a couple of independent human editors, one to
mediate between Jacob and c.l.c, another to mediate between c.l.c
and Jacob.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top