By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,750 Members | 1,221 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,750 IT Pros & Developers. It's quick & easy.

supplementary C frequent answers

P: n/a
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc

--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x1f6},*p=
b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case
2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Nov 14 '05 #1
Share this Question
Share on Google+
26 Replies


P: n/a
"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


From that website:
"Using strncpy() into a large buffer can be very inefficient. strncpy()
always
writes to every byte in the destination buffer, which can waste a lot of
time
if the destination buffer is much longer than the source string."

Isn't this a QoI issue? According to the Standard,

"The strncpy function copies not more than n characters (characters that
follow a null character are not copied) from the array pointed to by s2 to
the array pointed to by s1. If copying takes place between objects that
overlap, the behavior is undefined."

Please note the part in parenteses.

Also from your website,

"If the source string is longer than the size of the destination buffer,
then strncpy() doesn't write a terminating null. So a call to strncpy() must
be
followed by explicitly writing a null terminator at the end of the
destination
buffer in most cases."

Nothing simpler:

strncpy(dest, src, n)[n-1] = 0;

IMNSHO, strncpy() is far more advisable than strcpy().

Lastly, "off-topic guidance message" is a good title in a context of a
specific thread. As a general guidance, as e.g. on your website, it will
most likely go unnoticed ("I never write off-topic posts, why should I waste
my time reading it?").
Something like "comp.lang.c topicality guidance" might be better. Just my
£0.02.

Peter
Nov 14 '05 #2

P: n/a
Peter Pichler wrote:
"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc
From that website:
"Using strncpy() into a large buffer can be very
inefficient. strncpy() always writes to every byte
in the destination buffer, which can waste a lot of
time if the destination buffer is much longer than
the source string."

Isn't this a QoI issue?


No.
According to the Standard,

"The strncpy function copies not more than n characters (characters that
follow a null character are not copied) from the array pointed to by s2 to
the array pointed to by s1. If copying takes place between objects that
overlap, the behavior is undefined."

Please note the part in parenteses.
Please note the very next sentence: "If the array pointed to by s2 is a
string that is shorter than n characters, null characters are appended to
the copy in the array pointed to by s1, until n characters in all have been
written."
Also from your website,

"If the source string is longer than the size of the destination buffer,
then strncpy() doesn't write a terminating null. So a call to strncpy()
must be followed by explicitly writing a null terminator at the end of the
destination buffer in most cases."

Nothing simpler:

strncpy(dest, src, n)[n-1] = 0;
Easy to forget to do that, though, and it assumes that dest is at least n
bytes long, which it might not be.
IMNSHO, strncpy() is far more advisable than strcpy().
That's like saying a screwdriver is more advisable than a hammer. It depends
on what you're trying to do. strncpy's job is to copy part of a string,
whereas strcpy's job is to copy a whole string. It is silly to use strncpy
if your objective is to copy the whole string.
Lastly, "off-topic guidance message" is a good title in a context of a
specific thread. As a general guidance, as e.g. on your website, it will
most likely go unnoticed ("I never write off-topic posts, why should I
waste my time reading it?").
Something like "comp.lang.c topicality guidance" might be better. Just my
£0.02.


Better, and it suggested "Guidance on finding the best newsgroup for your
question" to me as a (rather verbose but otherwise perhaps more friendly)
possibility.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #3

P: n/a
Peter Pichler wrote:

"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


From that website:
"Using strncpy() into a large buffer can be
very inefficient. strncpy() always writes to every byte in the
destination buffer, which can waste a lot of time
if the destination buffer is much longer than the source string."

Isn't this a QoI issue?


If you strncpy a zero length string source to
a hundred byte length string destination,
101 bytes of the destination string will be overwritten.

If you strcpy a zero length string source to
a hundred byte length string destination,
1 byte of the destination string will be overwritten.

--
pete
Nov 14 '05 #4

P: n/a
Richard Heathfield wrote:
Peter Pichler wrote:
"If the source string is longer than the size of the destination buffer,
then strncpy() doesn't write a terminating null. So a call to strncpy()
must be followed by explicitly writing a null terminator at the end of the
destination buffer in most cases."

Nothing simpler:

strncpy(dest, src, n)[n-1] = 0;


Easy to forget to do that, though, and it assumes that dest is at least n
bytes long, which it might not be.


If dest is less than n bytes long then the call to strncpy() is broken
already.

Jeremy.
Nov 14 '05 #5

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
Peter Pichler wrote: (about strncpy() being inefiicient)
Isn't this a QoI issue?


No.

Please note the very next sentence: "If the array pointed to by s2 is a
string that is shorter than n characters, null characters are appended to
the copy in the array pointed to by s1, until n characters in all have

been written."
Doh! Richard, was it you running the reading for comprehension course? Where
can I enroll?
IMNSHO, strncpy() is far more advisable than strcpy().


That's like saying a screwdriver is more advisable than a hammer. It

depends on what you're trying to do. strncpy's job is to copy part of a string,
whereas strcpy's job is to copy a whole string. It is silly to use strncpy
if your objective is to copy the whole string.


In many cases, you don't know how long the source string is. If I should
call strlen() first to find out, I could just as well use strncpy().

Peter
Nov 14 '05 #6

P: n/a
Ben Pfaff wrote:
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


| When are casts appropriate?
|
| Casts are generally undesirable, but there are several situations
| where a cast legitimately comes in handy:
[...]
| * Passing a null pointer to a varargs function.

More generally, calling a varargs function with any value whose type
isn't compatible with what the function expects.

Jeremy.
Nov 14 '05 #7

P: n/a
[Somebody] said
IMNSHO, strncpy() is far more advisable than strcpy().
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
That's like saying a screwdriver is more advisable than a hammer. It depends
on what you're trying to do. strncpy's job is to copy part of a string,
whereas strcpy's job is to copy a whole string. It is silly to use strncpy
if your objective is to copy the whole string.


That's a slightly limited way of looking at it; you could also say
that strncpy's "job" is to copy all of a string up to a limit. Having
that limit be within the target buffer's boundaries can be useful.

"Peter Pichler" <pi*****@pobox.sk> writes:
In many cases, you don't know how long the source string is. If I should
call strlen() first to find out, I could just as well use strncpy().


All else being equal. In practice, I often find that the length may
be needed for other reasons. I wouldn't bother making this point to a
beginner, though.
--
Lowell Gilbert, embedded/networking software engineer, Boston area:
resume/CV at http://be-well.ilk.org:8088/~lowell/resume/
username/password "public"
Nov 14 '05 #8

P: n/a
Peter Pichler wrote:

<snip>
> IMNSHO, strncpy() is far more advisable than strcpy().


That's like saying a screwdriver is more advisable than a hammer. It

depends
on what you're trying to do. strncpy's job is to copy part of a string,
whereas strcpy's job is to copy a whole string. It is silly to use
strncpy if your objective is to copy the whole string.


In many cases, you don't know how long the source string is. If I should
call strlen() first to find out, I could just as well use strncpy().


Um, I think you really *should* sign up for that course, Peter. :-)

If you need the whole string, you simply *have* to know how much storage
you'll need if you want to make a copy of it, and you *must* have the right
amount of storage available.

Having ascertained that "this" will fit into "that", by all means call
strncpy instead of strncpy if you really like typing all that much, but it
adds no extra safety and does not communicate your intent as well as strcpy
does.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #9

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bt**********@sparta.btinternet.com...
Peter Pichler wrote:
In many cases, you don't know how long the source string is. If I should
call strlen() first to find out, I could just as well use strncpy().
Um, I think you really *should* sign up for that course, Peter. :-)


("that" being "reading for comprehension", just for the benefit of innocent
bystanders)

No doubt ;-)
If you need the whole string, you simply *have* to know how much storage
you'll need if you want to make a copy of it, and you *must* have the right amount of storage available.


Perhaps we both need the course ;-) What if I don't care about the /whole/
string, but need to limit how much to copy because I know the length of the
destination buffer and know that it may not be long enough? Strange as it
may seem, I have just recently appeared in exactly that situation. To be
fair, I did not realize that strncpy() filled up the remaining space with
zeros. <eom>

Peter
Nov 14 '05 #10

P: n/a
pete wrote:

Peter Pichler wrote:

"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc
From that website:
"Using strncpy() into a large buffer can be
very inefficient. strncpy() always writes to every byte in the
destination buffer, which can waste a lot of time
if the destination buffer is much longer than the source string."

Isn't this a QoI issue?


If you strncpy a zero length string source to
a hundred byte length string destination,
101 bytes of the destination string will be overwritten.

Show me. strncpy() will write n characters to the destination.
If you strcpy a zero length string source to
a hundred byte length string destination,
1 byte of the destination string will be overwritten.

--
pete


--
Joe Wright http://www.jw-wright.com
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #11

P: n/a
Peter Pichler wrote:
What if I don't care about the /whole/
string, but need to limit how much to copy because I know the length of
the destination buffer and know that it may not be long enough?


If you don't care about the whole string, strcpy is the Wrong Thing for that
task, because strcpy /does/ copy the whole string.

Personally, I never use strncpy. If I care about the whole string, I make
sure the receiving buffer is big enough. If I don't care about the whole
string, I don't treat it /as/ a string (since the bit that I care about
/isn't/ a string), and I would favour mem* routines rather than str*
routines for that purpose.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #12

P: n/a
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Ben Pfaff wrote:
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


| When are casts appropriate?
|
| Casts are generally undesirable, but there are several situations
| where a cast legitimately comes in handy:
[...]
| * Passing a null pointer to a varargs function.

More generally, calling a varargs function with any value whose type
isn't compatible with what the function expects.


Most of the time, though, such conversions are more reasonably
done without a cast. (In my opinion, of course.)
--
"I hope, some day, to learn to read.
It seems to be even harder than writing."
--Richard Heathfield
Nov 14 '05 #13

P: n/a
"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


IMO, the article "why should toupper()'s argument be cast to unsigned char?"
is not explained very well.
What do you mean with "If char is signed, then some characters have negative
values". It could use an example.

I'd also elaborate about the valid return values from main in the article
"how should main be declared". Maybe the difference between implicit return
values in C89 and C99 would fit in there too (or put it in another article)

The article about malloc's return value could use an example for its third
point. "If you cast to the wrong type by accident, odd failures can result"
What odd failures? Convince me.
Nov 14 '05 #14

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> writes:
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Ben Pfaff wrote:
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


| When are casts appropriate?
|
| Casts are generally undesirable, but there are several situations
| where a cast legitimately comes in handy:
[...]
| * Passing a null pointer to a varargs function.

More generally, calling a varargs function with any value whose type
isn't compatible with what the function expects.


Most of the time, though, such conversions are more reasonably
done without a cast. (In my opinion, of course.)


Can you give some examples?

Here are a couple of cases where (IMHO) a cast is appropriate:

int *ptr = <whatever>;

printf("sizeof(ptr) = %d\n", (int)sizeof(ptr));
printf("ptr = [%p]\n", (void*)ptr);

In C99, you can avoid the cast in the first printf by using "%zu", but
that's not universally supported yet. (I might use unsigned long
rather than int, but I'm reasonably certain in this case that
sizeof(ptr) <= INT_MAX.)

In the second printf, I don't see a good way to avoid the cast.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #15

P: n/a
"Servé Lau" <la*****@home.nl> writes:
"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc
IMO, the article "why should toupper()'s argument be cast to unsigned char?"
is not explained very well.
What do you mean with "If char is signed, then some characters have negative
values". It could use an example.


Okay, I've updated it. (Changes may take a minute or two to
propagate.)
I'd also elaborate about the valid return values from main in the article
"how should main be declared". Maybe the difference between implicit return
values in C89 and C99 would fit in there too (or put it in another article)
Sure, good suggestion.
The article about malloc's return value could use an example for its third
point. "If you cast to the wrong type by accident, odd failures can result"
What odd failures? Convince me.


I don't recall at the moment, but it's definitely true--I've seen
them. Alignment-related failures surely, and I think there are
others.
--
"For those who want to translate C to Pascal, it may be that a lobotomy
serves your needs better." --M. Ambuhl

"Here are the steps to create a C-to-Turbo-Pascal translator..." --H. Schildt
Nov 14 '05 #16

P: n/a
Ben Pfaff wrote:
"Serve' Lau" <la*****@home.nl> writes:
The article about malloc's return value could use an example for its
third point. "If you cast to the wrong type by accident, odd failures can
result" What odd failures? Convince me.


I don't recall at the moment, but it's definitely true--I've seen
them. Alignment-related failures surely, and I think there are
others.


Consider a C90 implementation which stores returned pointers in one
register, and returned integers in another. If you forget to provide a
correct prototype for a function returning a pointer, such as malloc, the
implementation is obliged to assume that the function in question returns
int, rather than a pointer type, and therefore your code could receive a
garbage value from the integer register rather than the value that malloc
actually returns, which the implementation correctly stores in the pointer
register.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #17

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
Ben Pfaff wrote:
"Serve' Lau" <la*****@home.nl> writes:
The article about malloc's return value could use an example for its
third point. "If you cast to the wrong type by accident, odd failures can result" What odd failures? Convince me.


I don't recall at the moment, but it's definitely true--I've seen
them. Alignment-related failures surely, and I think there are
others.


Consider a C90 implementation which stores returned pointers in one
register, and returned integers in another. If you forget to provide a
correct prototype for a function returning a pointer, such as malloc [...]


With more missing context in this message, I thought that he was talking
about /having/ a prototype yet casting to the wrong type. Can you see any
problems with that other than failing to compile?
Nov 14 '05 #18

P: n/a
Richard Heathfield <do******@address.co.uk.invalid> writes:
Ben Pfaff wrote:
"Serve' Lau" <la*****@home.nl> writes:
The article about malloc's return value could use an example for its
third point. "If you cast to the wrong type by accident, odd failures can
result" What odd failures? Convince me.


I don't recall at the moment, but it's definitely true--I've seen
them. Alignment-related failures surely, and I think there are
others.


Consider a C90 implementation which stores returned pointers in one
register, and returned integers in another. If you forget to provide a
correct prototype for a function returning a pointer, such as malloc, the
implementation is obliged to assume that the function in question returns
int, rather than a pointer type, and therefore your code could receive a
garbage value from the integer register rather than the value that malloc
actually returns, which the implementation correctly stores in the pointer
register.


Such a problem would be covered by the second point, "Casting its
return value can mask a failure to #include <stdlib.h>, which
leads to undefined behavior." We are discussing the third point,
"If you cast to the wrong type by accident, odd failures can
result."
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz
Nov 14 '05 #19

P: n/a
Ben Pfaff wrote:

<snip>
Such a problem would be covered by the second point, "Casting its
return value can mask a failure to #include <stdlib.h>, which
leads to undefined behavior." We are discussing the third point,
"If you cast to the wrong type by accident, odd failures can
result."


Oops. Sorry about that.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #20

P: n/a
Peter Pichler wrote:
With more missing context in this message, I thought that he was talking
about /having/ a prototype yet casting to the wrong type. Can you see any
problems with that other than failing to compile?


Not without thinking about it, and perhaps not even then. Note to self:
"sign up for my own refresher course in Reading For Comprehension..."

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #21

P: n/a
Joe Wright wrote:

pete wrote:

Peter Pichler wrote:

"Ben Pfaff" <bl*@cs.stanford.edu> wrote in message
news:87************@pfaff.stanford.edu...
> Over the last couple of years, and especially recently, I've
> built up a few "stock" answers that supplement the C FAQ. If
> anyone wants to review and comment on them, I've just now put
> them up on my webpage, at
> http://benpfaff.org/writings/clc

From that website:
"Using strncpy() into a large buffer can be
very inefficient. strncpy() always writes to every byte in the
destination buffer, which can waste a lot of time
if the destination buffer is much longer than the source string."

Isn't this a QoI issue?


If you strncpy a zero length string source to
a hundred byte length string destination,
101 bytes of the destination string will be overwritten.

Show me. strncpy() will write n characters to the destination.


Yes, strncpy() will write n characters to the destination.
What I meant to say, but missed by a lot,
is that for cases where there are less than n bytes in string s2,
that strncpy will write more characters than strcpy will
for the same s1 and s2.

--
pete
Nov 14 '05 #22

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> wrote in
news:87************@pfaff.stanford.edu:
Richard Heathfield <do******@address.co.uk.invalid> writes:
Ben Pfaff wrote:
> "Serve' Lau" <la*****@home.nl> writes:
>
>> The article about malloc's return value could use an example for
>> its third point. "If you cast to the wrong type by accident, odd
>> failures can result" What odd failures? Convince me.
>
> I don't recall at the moment, but it's definitely true--I've seen
> them. Alignment-related failures surely, and I think there are
> others.


Consider a C90 implementation which stores returned pointers in one
register, and returned integers in another. If you forget to provide
a correct prototype for a function returning a pointer, such as
malloc, the implementation is obliged to assume that the function in
question returns int, rather than a pointer type, and therefore your
code could receive a garbage value from the integer register rather
than the value that malloc actually returns, which the implementation
correctly stores in the pointer register.


Such a problem would be covered by the second point, "Casting its
return value can mask a failure to #include <stdlib.h>, which
leads to undefined behavior." We are discussing the third point,
"If you cast to the wrong type by accident, odd failures can
result."


Trivial possible example:

You have a machine where all types must be aligned to a boundary the same
as the types size: it can do 8-bit transfers from any 8 bit boundary, 16-
bit transfers from any 16-bit boundary and so on. The machine has
different instructions to read different sized values, and uses an index
system so that:

LD8 A,42 loads the 8 bit value at the 43rd address,
LD16 B, 42 loads the 16 bit value at the 43rd 16-bit address (coinciding
with the 84th and 85th 8-bit address)
and so on.

On this machine, a void pointer is going to be a flat address like that
used with LD8. A cast to a 16-bit short will perform a right shift.

Using a pointer to the wrong type will mean reading from the wrong
address.

I don't know of any machines which actually do this, but I'm sure that
something like it exists somewhere! (The ARM is somewhat like this,
especially since you can shifts with memory-load instructions without
cost. You could index different sized types in this way.)

Ian Woods
Nov 14 '05 #23

P: n/a
"Ian Woods" <ne******@wuggyNOCAPS.org> wrote:
Ben Pfaff wrote:
> "Serve' Lau" <la*****@home.nl> writes:
>
>> The article about malloc's return value could use an example for
>> its third point. "If you cast to the wrong type by accident, odd
>> failures can result" What odd failures? Convince me.
>
> I don't recall at the moment, but it's definitely true--I've seen
> them. Alignment-related failures surely, and I think there are
> others.


Trivial possible example:

You have a machine where all types must be aligned to a boundary the same
as the types size: it can do 8-bit transfers from any 8 bit boundary, 16-
bit transfers from any 16-bit boundary and so on. The machine has
different instructions to read different sized values, and uses an index
system so that:

LD8 A,42 loads the 8 bit value at the 43rd address,
LD16 B, 42 loads the 16 bit value at the 43rd 16-bit address (coinciding
with the 84th and 85th 8-bit address)
and so on.

On this machine, a void pointer is going to be a flat address like that
used with LD8. A cast to a 16-bit short will perform a right shift.

Using a pointer to the wrong type will mean reading from the wrong
address.


Yes, but... malloc() returns an address properly aligned for any type.
In other words, even if you cast void* to any wider type*, thus losing
the lowest bits of the address, it's no real loss because those bits
must have been zeros anyway. You have to cast again b efore assigning
to a pointer, otherwise it would not compile at all.

NB: I understand that we are talking about cases like

double *p = (int*)malloc(sizeof *p);

This would not compile, unless your compiler is seriously broken.
To make it compile, you would have to cast again, e.g.

double *p = (double*)(int*)malloc(sizeof *p);

I cannot see any possible problems with that, other than it is UGLY,
provided that stdlib.h is #included.

The problems that Ben encountered may have been something like

double *p = (double*)malloc(sizeof(int));

Because *p used to be int*, but changed to double*, and the programmer
failed to notice that (s)he had to change the parameter as well. This
may even work by accident, if the implementation allocates memory in
segments, making such bugs even more difficult to spot.

Peter Pichler
Nov 14 '05 #24

P: n/a
Ben Pfaff wrote:

Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc


In "Why should toupper()'s argument be cast to unsigned
char?" the second (?) bulleted exception appears garbled:

. But these implementations are invariably free-
standing, meaning that they don't implement the
character handling functions anyway.)

In "How should malloc()'s return value be used?" the
second argument against casting is beginning to lose its
force. As of C99, the cast cannot mask the error.

In "How should sizeof be used in malloc()'s argument?"
the second reason given isn't quite right. It's not "the
sizeof syntax" that is self-evidently correct (the compiler,
after all, will complain loudly about syntax errors), but
the agreement between the type pointed to and the type of
sizeof's operand.

In "How can I shuffle the contents of an array?" I'm
not sure why shuffle() uses `j = i + rand() % (n - i)'
instead of the apparently simpler `j = rand() % (i + 1)'.
The important thing, of course, is *not* to use the still
simpler but biased `j = rand() % n'.

Also, the discussion might be improved (or might not;
de gustibus) by making two additional points:

- `rand() % N' is not an especially good idiom for
a random integer in [0,N). The FAQ suggests one
alternative; rejection is another.

- For the particular case of shuffling a simulated
deck of 52 playing cards, note that rand() can
deliver no more than UINT_MAX distinct sequences.
UINT_MAX is about 4e9 on most implementations but
52 factorial is about 8e67, so the vast majority
of shuffled decks are unattainable. (A 226-bit
or wider `unsigned' would overcome this problem.)

--
Er*********@sun.com
Nov 14 '05 #25

P: n/a
Eric Sosman <Er*********@sun.com> writes:
Ben Pfaff wrote:

Over the last couple of years, and especially recently, I've
built up a few "stock" answers that supplement the C FAQ. If
anyone wants to review and comment on them, I've just now put
them up on my webpage, at
http://benpfaff.org/writings/clc
In "Why should toupper()'s argument be cast to unsigned
char?" the second (?) bulleted exception appears garbled:

. But these implementations are invariably free-
standing, meaning that they don't implement the
character handling functions anyway.)


Hmm. Turns out to be a bug in my (almost)-plaintext-to-HTML
translator. Fixed.
In "How should malloc()'s return value be used?" the
second argument against casting is beginning to lose its
force. As of C99, the cast cannot mask the error.
Good point, noted.
In "How should sizeof be used in malloc()'s argument?"
the second reason given isn't quite right. It's not "the
sizeof syntax" that is self-evidently correct (the compiler,
after all, will complain loudly about syntax errors), but
the agreement between the type pointed to and the type of
sizeof's operand.
Ditto.
In "How can I shuffle the contents of an array?" I'm
not sure why shuffle() uses `j = i + rand() % (n - i)'
instead of the apparently simpler `j = rand() % (i + 1)'.
The important thing, of course, is *not* to use the still
simpler but biased `j = rand() % n'.
As is, the expression is the clearest way for me to visualize
what's going on the array. Each successive element of the array
becomes a randomly selected element taken from the as-yet
unvisited segment of the array. Your suggestion would require
moving backward in the array and I just have trouble visualizing
it for some reason. Because it (probably) wouldn't be any faster
to do it your way in practice, I write it the way that's clearest
to me.
Also, the discussion might be improved (or might not;
de gustibus) by making two additional points:

- `rand() % N' is not an especially good idiom for
a random integer in [0,N). The FAQ suggests one
alternative; rejection is another.

- For the particular case of shuffling a simulated
deck of 52 playing cards, note that rand() can
deliver no more than UINT_MAX distinct sequences.
UINT_MAX is about 4e9 on most implementations but
52 factorial is about 8e67, so the vast majority
of shuffled decks are unattainable. (A 226-bit
or wider `unsigned' would overcome this problem.)


Good points, updated.

Updates should propagate within half an hour or so.
--
"...Almost makes you wonder why Heisenberg didn't include postinc/dec operators
in the uncertainty principle. Which of course makes the above equivalent to
Schrodinger's pointer..."
--Anthony McDonald
Nov 14 '05 #26

P: n/a
Keith Thompson <ks***@mib.org> writes:
Ben Pfaff <bl*@cs.stanford.edu> writes:
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Ben Pfaff wrote:
| Casts are generally undesirable, but there are several situations
| where a cast legitimately comes in handy:
[...]
| * Passing a null pointer to a varargs function.

More generally, calling a varargs function with any value whose type
isn't compatible with what the function expects.


Most of the time, though, such conversions are more reasonably
done without a cast. (In my opinion, of course.)


Can you give some examples?

Here are a couple of cases where (IMHO) a cast is appropriate:

int *ptr = <whatever>;

printf("sizeof(ptr) = %d\n", (int)sizeof(ptr));
printf("ptr = [%p]\n", (void*)ptr);

In C99, you can avoid the cast in the first printf by using "%zu", but
that's not universally supported yet. (I might use unsigned long
rather than int, but I'm reasonably certain in this case that
sizeof(ptr) <= INT_MAX.)

In the second printf, I don't see a good way to avoid the cast.


I think I agree with you now. I've updated the page and it
should propagate soon.
--
"It would be a much better example of undefined behavior
if the behavior were undefined."
--Michael Rubenstein
Nov 14 '05 #27

This discussion thread is closed

Replies have been disabled for this discussion.