Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > supplementary C frequent answers

Reply
Thread Tools

supplementary C frequent answers

 
 
Richard Heathfield
Guest
Posts: n/a
 
      01-04-2004
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 : http://www.velocityreviews.com/forums/(E-Mail Removed)
"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
 
Reply With Quote
 
 
 
 
pete
Guest
Posts: n/a
 
      01-04-2004
Joe Wright wrote:
>
> pete wrote:
> >
> > Peter Pichler wrote:
> > >
> > > "Ben Pfaff" <(E-Mail Removed)> wrote in message
> > > news:(E-Mail Removed)...
> > > > 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
 
Reply With Quote
 
 
 
 
Ian Woods
Guest
Posts: n/a
 
      01-04-2004
Ben Pfaff <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

> Richard Heathfield <(E-Mail Removed)> writes:
>
>> Ben Pfaff wrote:
>>
>> > "Serve' Lau" <(E-Mail Removed)> 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
 
Reply With Quote
 
Peter Pichler
Guest
Posts: n/a
 
      01-04-2004
"Ian Woods" <(E-Mail Removed)> wrote:
> >> Ben Pfaff wrote:
> >> > "Serve' Lau" <(E-Mail Removed)> 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


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      01-05-2004
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.)

--
(E-Mail Removed)
 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      01-05-2004
Eric Sosman <(E-Mail Removed)> 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
 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      01-05-2004
Keith Thompson <(E-Mail Removed)> writes:

> Ben Pfaff <(E-Mail Removed)> writes:
> > Jeremy Yallop <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strsup - supplementary string functions Malcolm McLean C Programming 19 02-03-2013 10:33 PM
[RFC] PEP 3143: supplementary group list concerns Jan Pokorný Python 1 03-11-2012 11:41 PM
frequent crashes with US Robotics 8054 22MB/s wireless card NGI Wireless Networking 0 10-27-2004 01:40 PM
Frequent Disconnections David McKinnon Wireless Networking 13 06-24-2004 08:03 PM
Supplementary groups Andrew Walrond Ruby 0 11-20-2003 12:18 AM



Advertisments