Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Initialiazing a malloced struct to all-0

Reply
Thread Tools

Initialiazing a malloced struct to all-0

 
 
Noob
Guest
Posts: n/a
 
      04-25-2013
Hello everyone,

Typically when I want to initialize an auto struct to
"all-0" values, I write

struct foo bar = { 0 };

and let the compiler correctly set arithmetic values
to the appropriate 0 or 0.0 and pointers to NULL.

But when I have a malloced struct, I am often tempted
to write

struct foo *bar = malloc(sizeof *bar);
memset(bar, 0, sizeof *bar);

even though I know this is not guaranteed to set
floating-point fields to 0.0 and pointers to NULL.

What are my options then? I suppose I should write

struct foo zero = { 0 };
struct foo *bar = malloc(sizeof *bar);
*bar = zero;

to get the behavior I want, safely?

Regards.
 
Reply With Quote
 
 
 
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      04-25-2013
Noob <root@127.0.0.1> wrote:

> Typically when I want to initialize an auto struct to
> "all-0" values, I write


> struct foo bar = { 0 };


> and let the compiler correctly set arithmetic values
> to the appropriate 0 or 0.0 and pointers to NULL.


> But when I have a malloced struct, I am often tempted
> to write


> struct foo *bar = malloc(sizeof *bar);
> memset(bar, 0, sizeof *bar);


> even though I know this is not guaranteed to set
> floating-point fields to 0.0 and pointers to NULL.


While it is true that floating point zero doesn't have to
be all zero bits, hardware designers would have to have a very
good reason for not doing it. (Assuming that they want people
to buy and use the hardware.)

Even more, consider the fate of a hardware designer for a system
where all zero bits was not an integer zero?

-- glen
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      04-25-2013
glen herrmannsfeldt <(E-Mail Removed)> writes:
> Noob <root@127.0.0.1> wrote:
>
>> Typically when I want to initialize an auto struct to
>> "all-0" values, I write

>
>> struct foo bar = { 0 };

>
>> and let the compiler correctly set arithmetic values
>> to the appropriate 0 or 0.0 and pointers to NULL.

>
>> But when I have a malloced struct, I am often tempted
>> to write

>
>> struct foo *bar = malloc(sizeof *bar);
>> memset(bar, 0, sizeof *bar);

>
>> even though I know this is not guaranteed to set
>> floating-point fields to 0.0 and pointers to NULL.

>
> While it is true that floating point zero doesn't have to
> be all zero bits, hardware designers would have to have a very
> good reason for not doing it. (Assuming that they want people
> to buy and use the hardware.)
>
> Even more, consider the fate of a hardware designer for a system
> where all zero bits was not an integer zero?


Such an implementation would violate the C standard, which says:

For any integer type, the object representation where all the bits
are zero shall be a representation of the value zero in that type.

That was added by one of the Technical Corrigenda to C99.

(There's no such requirement for pointer or floating-point types.

At least for pointers, there could be a very good reason to make null
something other than all-bits-zero. I once worked on a (non-C) system
that used 0x00000001 as its null pointer representation because the
hardware would trap on an attempt to dereference an odd address (at
least for types bigger than one byte).

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Werner Wenzel
Guest
Posts: n/a
 
      04-25-2013
Am 25.04.2013 21:19, schrieb Keith Thompson:
> glen herrmannsfeldt <(E-Mail Removed)> writes:
>> Noob <root@127.0.0.1> wrote:
>>
>>> Typically when I want to initialize an auto struct to
>>> "all-0" values, I write

>>
>>> struct foo bar = { 0 };

>>
>>> and let the compiler correctly set arithmetic values
>>> to the appropriate 0 or 0.0 and pointers to NULL.

>>
>>> But when I have a malloced struct, I am often tempted
>>> to write

>>
>>> struct foo *bar = malloc(sizeof *bar);
>>> memset(bar, 0, sizeof *bar);

>>
>>> even though I know this is not guaranteed to set
>>> floating-point fields to 0.0 and pointers to NULL.

>>
>> While it is true that floating point zero doesn't have to
>> be all zero bits, hardware designers would have to have a very
>> good reason for not doing it. (Assuming that they want people
>> to buy and use the hardware.)
>>
>> Even more, consider the fate of a hardware designer for a system
>> where all zero bits was not an integer zero?

>
> Such an implementation would violate the C standard, which says:
>
> For any integer type, the object representation where all the bits
> are zero shall be a representation of the value zero in that type.
>
> That was added by one of the Technical Corrigenda to C99.
>
> (There's no such requirement for pointer or floating-point types.
>
> At least for pointers, there could be a very good reason to make null
> something other than all-bits-zero. I once worked on a (non-C) system
> that used 0x00000001 as its null pointer representation because the
> hardware would trap on an attempt to dereference an odd address (at
> least for types bigger than one byte).
>

Does this still hold?

The C11 standard (actually N1570 Committee Draft April 12, 2011) says in
paragraph 6.3.2.3 Pointers, #3: "An integer constant expression with the
value 0, or such an expression cast to type void *, is called a null
pointer constant."

And in footnote #66: "The macro NULL is defined in <stddef.h> (and other
headers) as a null pointer constant; see 7.19."

(Although paragraph 7.19 Common definitions <stddef.h>, #3, describes
NULL as an "implementation-defined" null pointer constant.)

If so, why not just use calloc instead of malloc?

Werner Wenzel

 
Reply With Quote
 
Tim Prince
Guest
Posts: n/a
 
      04-25-2013
On 04/25/2013 03:19 PM, Keith Thompson wrote:
> glen herrmannsfeldt <(E-Mail Removed)> writes:
>> Noob <root@127.0.0.1> wrote:
>>
>>> Typically when I want to initialize an auto struct to
>>> "all-0" values, I write

>>
>>> struct foo bar = { 0 };

>>
>>> and let the compiler correctly set arithmetic values
>>> to the appropriate 0 or 0.0 and pointers to NULL.

>>
>>> But when I have a malloced struct, I am often tempted
>>> to write

>>
>>> struct foo *bar = malloc(sizeof *bar);
>>> memset(bar, 0, sizeof *bar);

>>
>>> even though I know this is not guaranteed to set
>>> floating-point fields to 0.0 and pointers to NULL.

>>
>> While it is true that floating point zero doesn't have to
>> be all zero bits, hardware designers would have to have a very
>> good reason for not doing it. (Assuming that they want people
>> to buy and use the hardware.)
>>
>> Even more, consider the fate of a hardware designer for a system
>> where all zero bits was not an integer zero?

>
> Such an implementation would violate the C standard, which says:
>
> For any integer type, the object representation where all the bits
> are zero shall be a representation of the value zero in that type.
>
> That was added by one of the Technical Corrigenda to C99.
>
> (There's no such requirement for pointer or floating-point types.
>
> At least for pointers, there could be a very good reason to make null
> something other than all-bits-zero. I once worked on a (non-C) system
> that used 0x00000001 as its null pointer representation because the
> hardware would trap on an attempt to dereference an odd address (at
> least for types bigger than one byte).
>

I last worked on a system where all-bits-zero was not a floating point
zero back in 1985. It was a non-normalized floating point zero, one of
the consequences being that adding FLT_EPSILON/2 to it would produce
underflow. I think IEEE-754 was set up intentionally to encourage use of
all-bits-zero as a normal zero. So, although C covers such cases, their
undesirability has eased them into extinction.
Unless you count the systems of the 80's where int was stored in 32 bits
of a 64-bit word and didn't affect the other 32 bits, which were
invisible to integer arithmetic (but were affected by | ^ & operators).
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-25-2013
Werner Wenzel <(E-Mail Removed)> writes:
> Am 25.04.2013 21:19, schrieb Keith Thompson:
>> glen herrmannsfeldt <(E-Mail Removed)> writes:

[...]
>>> Even more, consider the fate of a hardware designer for a system
>>> where all zero bits was not an integer zero?

>>
>> Such an implementation would violate the C standard, which says:
>>
>> For any integer type, the object representation where all the bits
>> are zero shall be a representation of the value zero in that type.
>>
>> That was added by one of the Technical Corrigenda to C99.
>>
>> (There's no such requirement for pointer or floating-point types.
>>
>> At least for pointers, there could be a very good reason to make null
>> something other than all-bits-zero. I once worked on a (non-C) system
>> that used 0x00000001 as its null pointer representation because the
>> hardware would trap on an attempt to dereference an odd address (at
>> least for types bigger than one byte).
>>

> Does this still hold?


Yes.

> The C11 standard (actually N1570 Committee Draft April 12, 2011) says
> in paragraph 6.3.2.3 Pointers, #3: "An integer constant expression
> with the value 0, or such an expression cast to type void *, is called
> a null pointer constant."


The C90 and C99 standards say the same thing.

This says nothing about the *representation* of a null pointer, which is
commonly all-bits-zero but needn't be.

If you write:

void *ptr = 0;

there's an implicit conversion of the null pointer constant 0 to type
void*. That conversion may not be trivial; for example, it could result
in a stored pointer value with a representation of, say, 0xffffffff.

> And in footnote #66: "The macro NULL is defined in <stddef.h> (and
> other headers) as a null pointer constant; see 7.19."
>
> (Although paragraph 7.19 Common definitions <stddef.h>, #3, describes
> NULL as an "implementation-defined" null pointer constant.)
>
> If so, why not just use calloc instead of malloc?


Because calloc() doesn't necessarily set pointers to null or
floating-point objects to 0.0.

And because, in many (but not all) cases, zeroing allocated memory is a
waste of time if your program doesn't read objects until after it's
explicitly written to them. Furthermore, a compiler can perform data
flow analysis that can tell you, in some cases, when you've read an
uninitialized object; initializing it to zero makes such analysis
impossible.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      04-25-2013
On Thu, 25 Apr 2013 17:10:55 +0200, Noob wrote:

> But when I have a malloced struct, I am often tempted
> to write
>
> struct foo *bar = malloc(sizeof *bar);
> memset(bar, 0, sizeof *bar);
>
> even though I know this is not guaranteed to set
> floating-point fields to 0.0 and pointers to NULL.
>
> What are my options then?


Write a configure test to check that the platform uses all-zeros for 0.0
and NULL, and generate a "this program will not work on your system" error
if it doesn't.

There isn't actually a law requiring C code to be portable to every system
with a conforming C implementation.

Or do you allow for the case where sizeof(void*)>sizeof(size_t) (i.e.
8086 "compact" and "large" memory models)?

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-25-2013
On 04/25/2013 05:18 PM, Werner Wenzel wrote:
> Am 25.04.2013 21:19, schrieb Keith Thompson:

....
>> For any integer type, the object representation where all the bits
>> are zero shall be a representation of the value zero in that type.
>>
>> That was added by one of the Technical Corrigenda to C99.
>>
>> (There's no such requirement for pointer or floating-point types.
>>
>> At least for pointers, there could be a very good reason to make null
>> something other than all-bits-zero. I once worked on a (non-C) system
>> that used 0x00000001 as its null pointer representation because the
>> hardware would trap on an attempt to dereference an odd address (at
>> least for types bigger than one byte).
>>

> Does this still hold?
>
> The C11 standard (actually N1570 Committee Draft April 12, 2011) says in
> paragraph 6.3.2.3 Pointers, #3: "An integer constant expression with the
> value 0, or such an expression cast to type void *, is called a null
> pointer constant."
>
> And in footnote #66: "The macro NULL is defined in <stddef.h> (and other
> headers) as a null pointer constant; see 7.19."


That's not a change from C99, and there's no contradiction here. A null
pointer constant, if used in various contexts, gets implicitly converted
to a null pointer. That null pointer, if saved in a pointer object, will
have a representation. Just because the null pointer constant
necessarily involves a integer expression with a value of 0 doesn't mean
that representation of null pointer must have all bits 0.

#include <assert.h>
int main(void)
{
void *p = 0;
int i = 0;
void *q = (void*)i;
unsigned char array[sizeof p] = {0};

assert(p==q);
// If we've reached this point, q is a null pointer.
assert(memcmp(&p, &q, sizeof p));
assert(memcmp(&p, array, sizeof p));
return 0
}

Note that i is an integer expression with a value of zero, but it is not
an integer constant expression, because 'i' doesn't qualify as any of
the things allowed by 6.6p6 in integer constant expressions. Therefore,
there is no null pointer constant here involved in the initialization of
q. The value of (void*)0 is therefore governed only by 6.3.2.3p5, which
allows, among other things, the possibility that q might have a trap
representation. Even if it isn't, it need not be a null pointer.
If q has a trap representation, the first assert() has undefined
behavior before it even gets a chance to be triggered. Even if that's
not the case, the C standard says nothing that prevents any of those
asserts from triggering.

> (Although paragraph 7.19 Common definitions <stddef.h>, #3, describes
> NULL as an "implementation-defined" null pointer constant.)


That's true. NULL can expand into 0, '\0', 0U, 0L, L'\0', (5-5), or
((short)3.14F - (long)3.41), (void*)0, among infinitely many other
possibilities. I don't know of any good reason for defining it as
anything other than 0 or (void*)0, but all of those other definitions
are allowed.

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-25-2013
James Kuyper <(E-Mail Removed)> writes:
[...]
> That's true. NULL can expand into 0, '\0', 0U, 0L, L'\0', (5-5), or
> ((short)3.14F - (long)3.41), (void*)0, among infinitely many other
> possibilities. I don't know of any good reason for defining it as
> anything other than 0 or (void*)0, but all of those other definitions
> are allowed.


NULL can't expand to (void*)0, because of N1570 7.1.2p5 (essentially
unchanged from earlier versions of the standard):

Any definition of an object-like macro described in this clause
shall expand to code that is fully protected by parentheses where
necessary, so that it groups in an arbitrary expression as if it
were a single identifier.

Without the parentheses, sizeof NULL would be a syntax error.

(An overly literal reading of the standard suggests that ((void*)0)
is also disallowed, because 6.5.1p5 doesn't say actually that a
parenthesized null pointer constant is a null pointer constant,
but I think the intent is clearly to allow it.)

One interesting way to define NULL would be:

enum { __NULL__ };
#define NULL __NULL__

It could make it easier for the compiler to diagnose misuses of NULL
(e.g., as a null character constant), since macros often are not
visible to the phase of the compiler that generates the diagnostics.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      04-25-2013
Tim Prince <(E-Mail Removed)> wrote:
> On 04/25/2013 03:19 PM, Keith Thompson wrote:
>> glen herrmannsfeldt <(E-Mail Removed)> writes:
>>> Noob <root@127.0.0.1> wrote:


(snip)

>>>> But when I have a malloced struct, I am often tempted
>>>> to write


>>>> struct foo *bar = malloc(sizeof *bar);
>>>> memset(bar, 0, sizeof *bar);


>>>> even though I know this is not guaranteed to set
>>>> floating-point fields to 0.0 and pointers to NULL.


(snip, then I wrote)
>>> While it is true that floating point zero doesn't have to
>>> be all zero bits, hardware designers would have to have a very
>>> good reason for not doing it. (Assuming that they want people
>>> to buy and use the hardware.)


>>> Even more, consider the fate of a hardware designer for a system
>>> where all zero bits was not an integer zero?


>> Such an implementation would violate the C standard, which says:


>> For any integer type, the object representation where all the bits
>> are zero shall be a representation of the value zero in that type.


But that doesn't stop people from trying to sell them. Demand will
be low from those hoping to run C programs on them.

>> That was added by one of the Technical Corrigenda to C99.


>> (There's no such requirement for pointer or floating-point types.


>> At least for pointers, there could be a very good reason to make null
>> something other than all-bits-zero. I once worked on a (non-C) system
>> that used 0x00000001 as its null pointer representation because the
>> hardware would trap on an attempt to dereference an odd address (at
>> least for types bigger than one byte).


Note that segment selector zero is special in Intel hardware starting
with the 80286 on through current systems, as the null selector.

> I last worked on a system where all-bits-zero was not a floating point
> zero back in 1985. It was a non-normalized floating point zero, one of
> the consequences being that adding FLT_EPSILON/2 to it would produce
> underflow. I think IEEE-754 was set up intentionally to encourage use of
> all-bits-zero as a normal zero. So, although C covers such cases, their
> undesirability has eased them into extinction.


In systems that don't have a hidden one, and allow for the possibility
of an unnormalized value, you can get surprising results adding values
with a zero significand and other than the smallest exponent.

Prenormalization for addition is based on the difference in the
exponents, usually before checking to see that the significand is zero.

For IBM hexadecimal floating point, for example, the Fortran AINT
(truncate to an integer value, but keep in floating point form) is
implemented by adding 0 with an exponetn of 7 (biased exponent X'47').
The exponent should have the smallest value, which is usually the
biased value of zero.

> Unless you count the systems of the 80's where int was stored in 32 bits
> of a 64-bit word and didn't affect the other 32 bits, which were
> invisible to integer arithmetic (but were affected by | ^ & operators).


The IBM 36 bit systems, such as the 704 and 7090, store floating point
values in 36 bits, and fixed point in 16 bits of a 36 bit word.
(Sign magnitude for those machines.)

As far as I know, still no C compiler for the 7090.

-- glen
 
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
Dynamic multidimensional array, deallocation of pointer not malloced.. welch.ryan@gmail.com C++ 18 05-13-2007 11:51 PM
Deallocation of a pointer not malloced, any tips? Kumar McMillan Python 0 04-19-2007 09:20 PM
Do I need to free all memory that is malloced? karthik.nar@gmail.com C Programming 21 09-29-2005 10:03 PM
malloced union member rohit C Programming 10 05-24-2004 08:24 AM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments