zero up memory

Discussion in 'C Programming' started by Mark, Jan 23, 2012.

  1. Mark

    Mark Guest

    Hello,

    consider the following code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>

    #define NAME_LEN 16
    #define MAX_INSTANCES 64

    struct inst_info
    {
    uint32_t state;
    uint32_t port_mem;
    };

    struct vid_entry
    {
    struct vid_entry *prev;
    struct vid_entry *next;
    uint16_t vid;
    uint32_t vid_state;
    };

    struct hsl
    {
    char name[NAME_LEN + 1];
    uint32_t ageing_time;
    unsigned char flags;
    int learning;

    /* Platform specific information. */
    void *system_info;

    struct vid_entry *inst_table[MAX_INSTANCES];
    struct inst_info inst_info_table[MAX_INSTANCES];
    };

    int main(void)
    {
    struct hsl *br;

    br = malloc (sizeof (struct hsl));
    if ( !br)
    {
    puts("malloc() failed");
    return -1;
    }

    memset ((void *)&br->inst_info_table, 0, sizeof (struct inst_info) *
    MAX_INSTANCES);
    memset ((void *)&br->inst_table, 0, sizeof (struct vid_entry *) *
    MAX_INSTANCES);

    free (br);

    return 0;
    }

    As I understand it, 'inst_table' is the array of pointers to 'struct
    vid_entry' and on my system pointer is 32-bit wide, so I want to make sure
    that the code is correctly initializing memory allocated for 'struct hsl'
    object.

    Also, is (void *) necessary or more a pedantic element?

    Thanks !

    Mark
     
    Mark, Jan 23, 2012
    #1
    1. Advertising

  2. "Mark" <> writes:

    > Hello,
    >
    > consider the following code:
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    > #include <stdint.h>
    >
    > #define NAME_LEN 16
    > #define MAX_INSTANCES 64
    >
    > struct inst_info
    > {
    > uint32_t state;
    > uint32_t port_mem;
    > };
    >
    > struct vid_entry
    > {
    > struct vid_entry *prev;
    > struct vid_entry *next;
    > uint16_t vid;
    > uint32_t vid_state;
    > };
    >
    > struct hsl
    > {
    > char name[NAME_LEN + 1];
    > uint32_t ageing_time;
    > unsigned char flags;
    > int learning;
    >
    > /* Platform specific information. */
    > void *system_info;
    >
    > struct vid_entry *inst_table[MAX_INSTANCES];
    > struct inst_info inst_info_table[MAX_INSTANCES];
    > };
    >
    > int main(void)
    > {
    > struct hsl *br;
    >
    > br = malloc (sizeof (struct hsl));
    > if ( !br)
    > {
    > puts("malloc() failed");
    > return -1;
    > }
    >
    > memset ((void *)&br->inst_info_table, 0, sizeof (struct inst_info) *
    > MAX_INSTANCES);
    > memset ((void *)&br->inst_table, 0, sizeof (struct vid_entry *) *
    > MAX_INSTANCES);
    >
    > free (br);
    >
    > return 0;
    > }
    >
    > As I understand it, 'inst_table' is the array of pointers to 'struct
    > vid_entry' and on my system pointer is 32-bit wide, so I want to make sure
    > that the code is correctly initializing memory allocated for 'struct hsl'
    > object.


    Well, it zeros only two elements of the struct hsl object. The other
    elements are still indeterminate.

    There is a technical issue that memset sets the memory to all zero bits
    whereas C permits a null pointer to be represented by something else.
    It's therefore possible that memset is setting the pointers to some
    undesirable value. You may spend your whole life without ever seeing
    such a system but, once you know about it, it's hard not to prefer a
    loop:

    for (int i = 0; i < MAX_INSTANCES; i++)
    br->inst_table = NULL;

    > Also, is (void *) necessary or more a pedantic element?


    No, it's not. Neither is the & since (in this situation) an array is
    converted to a pointer to it's first element. Also, you can simplify
    the code by making better use of sizeof:

    br = malloc (sizeof *br);

    Just by looking, I know sizeof *br is the right size -- I don't have to
    check the definition of br. Then later:

    memset (br->inst_info_table, 0, sizeof br->inst_info_table);
    memset (br->inst_table, 0, sizeof br->inst_table);

    --
    Ben.
     
    Ben Bacarisse, Jan 23, 2012
    #2
    1. Advertising

  3. Hello,

    It is a bit shorter if you do:

    br = calloc(1,sizeof (struct hsl));
    if ( !br)
    ....[as above]


    calloc implicitly zeroes the allocated memory(all the struct fields).
     
    Johann Klammer, Jan 23, 2012
    #3
  4. On Jan 23, 4:57 pm, Johann Klammer <1.net> wrote:
    >
    > calloc implicitly zeroes the allocated memory(all the struct fields).
    >

    Yes. Calloc() was specified before the C standard was worked out.

    All bits zero isn't necessarily a floating point zero, and it isn't
    necessarily a null pointer. Which makes calloc() pretty useless.

    --
    MiniBasic - how to write a script interpreter
    http://www.malcolmmclean.site11.com/www
     
    Malcolm McLean, Jan 23, 2012
    #4
  5. Malcolm McLean <> writes:
    > On Jan 23, 4:57 pm, Johann Klammer <1.net> wrote:
    >>
    >> calloc implicitly zeroes the allocated memory(all the struct fields).
    >>

    > Yes. Calloc() was specified before the C standard was worked out.
    >
    > All bits zero isn't necessarily a floating point zero, and it isn't
    > necessarily a null pointer. Which makes calloc() pretty useless.


    It's useful if the allocated memory doesn't contain any floating-point
    or pointer subobjects.

    (it can also, I hesitate to mention, be useful in code that isn't
    intended to be portable.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 23, 2012
    #5
  6. On Jan 23, 5:22 pm, Keith Thompson <> wrote:
    >
    > It's (calloc) useful if the allocated memory doesn't contain any floating-point
    > or pointer subobjects.
    >

    It's too easy to change a structure to add a floating point or pointer
    field, test it, and of course find that the code behaves exactly as
    you want.
    Calloc() is best avoided.

    --
    MinBasic - how to write a script interpreter
    http://www.malcolmmclean.site11.com/www
     
    Malcolm McLean, Jan 23, 2012
    #6
  7. Malcolm McLean <> writes:
    > On Jan 23, 5:22 pm, Keith Thompson <> wrote:
    >> It's (calloc) useful if the allocated memory doesn't contain any floating-point
    >> or pointer subobjects.
    >>

    > It's too easy to change a structure to add a floating point or pointer
    > field, test it, and of course find that the code behaves exactly as
    > you want.
    > Calloc() is best avoided.


    Agreed, mostly -- but if the allocated space contains an array of some
    integer type, it's not unreasonable to use calloc() (with a comment).
    But yes, there is a risk if the integer array is later changed to a
    floating-point array.

    (Hmm, I wonder if there are any systems where all-bits-zero is not a
    representation of 0.0 for all floating-point types. Could a future
    standard impose such a requirement without breaking existing
    implementations?)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 23, 2012
    #7
  8. Mark

    Kaz Kylheku Guest

    On 2012-01-23, Keith Thompson <> wrote:
    > Malcolm McLean <> writes:
    >> On Jan 23, 4:57 pm, Johann Klammer <1.net> wrote:
    >>>
    >>> calloc implicitly zeroes the allocated memory(all the struct fields).
    >>>

    >> Yes. Calloc() was specified before the C standard was worked out.
    >>
    >> All bits zero isn't necessarily a floating point zero, and it isn't
    >> necessarily a null pointer. Which makes calloc() pretty useless.

    >
    > It's useful if the allocated memory doesn't contain any floating-point
    > or pointer subobjects.


    It's useful even if it isn't, just no portable.

    Nonportable and useless are different things.

    I can think of a lot of code that will never need to run on a machine
    where null pointers or 0.0 aren't all zero bits.

    All-zero memory can be very efficiently procured on a virtual memory OS:
    you can alias all of the pages to the same physical frame of memory.

    This is very useful for, for instance, large sparse matrices.

    An architecture where zero bits don't make a 0.0 floating point value
    is plain stupid (and not IEEE 754 compatible).
     
    Kaz Kylheku, Jan 23, 2012
    #8
  9. On 01/23/2012 03:14 PM, Kaz Kylheku wrote:
    > An architecture where zero bits don't make a 0.0 floating point value
    > is plain stupid (and not IEEE 754 compatible).


    How about a 754 implementation where the in-core representation is the
    bitwise complement; that way the all-bits-zero memory word represent the
    all-bits-one datum which (on this hypothetical platform) is the
    signaling NaN.

    However crazy this may be, "plain stupid" it's not -- and it should be
    754 compliant.

    --Joel
     
    Joel C. Salomon, Jan 23, 2012
    #9
  10. On Jan 23, 8:14 pm, Kaz Kylheku <> wrote:
    >
    > An architecture where zero bits don't make a 0.0 floating point value
    > is plain stupid (and not IEEE 754 compatible).
    >

    Zero cannot be represented in floating point, because the exponent is
    minus infinity.

    If you have a signed exponent, zero would represent unity, or number
    within the range 1 - 2. You might reserve high bit set for special
    numbers, and zero could be one of those special numbers.
    Most existing floating point formats use an offset to represent
    exponents, so zero exponent represents the lowest representable value,
    and all bits zero can be used for zero. However this isn't
    particularly logical, and there might be low-level circuit reasons for
    preferring a two's complement exponent.
     
    Malcolm McLean, Jan 23, 2012
    #10
  11. Kaz Kylheku <> writes:

    > On 2012-01-23, Keith Thompson <> wrote:
    >> Malcolm McLean <> writes:
    >>> On Jan 23, 4:57 pm, Johann Klammer <1.net> wrote:
    >>>>
    >>>> calloc implicitly zeroes the allocated memory(all the struct fields).
    >>>>
    >>> Yes. Calloc() was specified before the C standard was worked out.
    >>>
    >>> All bits zero isn't necessarily a floating point zero, and it isn't
    >>> necessarily a null pointer. Which makes calloc() pretty useless.

    >>
    >> It's useful if the allocated memory doesn't contain any floating-point
    >> or pointer subobjects.

    >
    > It's useful even if it isn't, just no portable.


    Which is what Keith said immediately after the remark you quote. Why
    cut it? You could have left it in and still make the point you want to
    make (the insanity and scarcity of these odd architectures) without
    suggesting that Keith was excluding the use of calloc in non-portable
    code.

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Jan 23, 2012
    #11
  12. Malcolm McLean <> writes:

    > On Jan 23, 8:14 pm, Kaz Kylheku <> wrote:
    >>
    >> An architecture where zero bits don't make a 0.0 floating point value
    >> is plain stupid (and not IEEE 754 compatible).
    >>

    > Zero cannot be represented in floating point, because the exponent is
    > minus infinity.


    In systems where the mantissa is not normalised (i.e. there is no
    implicit leading 1) then zero is specified quite naturally with a zero
    mantissa. A zero sign bit and exponent (even it biased) makes no
    difference. Systems like this are common: IEEE decimal floating point
    and IBM's hexadecimal floating point come to mind.

    > If you have a signed exponent, zero would represent unity, or number
    > within the range 1 - 2. You might reserve high bit set for special
    > numbers, and zero could be one of those special numbers.
    > Most existing floating point formats use an offset to represent
    > exponents, so zero exponent represents the lowest representable value,
    > and all bits zero can be used for zero. However this isn't
    > particularly logical, and there might be low-level circuit reasons for
    > preferring a two's complement exponent.


    In IEEE binary floating point formats, a zero exponent is special. It
    is not simply the lowest exponent, but flags up a set of special values:
    +0 and -0 when the mantissa is 0 and denormalised numbers when it
    is not zero (and the actual exponent used is 1 not zero i.e. the lowest
    "real" exponent).

    --
    Ben.
     
    Ben Bacarisse, Jan 23, 2012
    #12
  13. On Jan 23, 11:21 pm, Ben Bacarisse <> wrote:
    >
    > In systems where the mantissa is not normalised (i.e. there is no
    > implicit leading 1) then zero is specified quite naturally with a zero
    > mantissa.  A zero sign bit and exponent (even it biased) makes no
    > difference.  Systems like this are common: IEEE decimal floating point
    > and IBM's hexadecimal floating point come to mind.
    >

    So how does the processor do equality comparisons, efficiently?

    If the mantissa is not normalized then there are many possible
    representations for each number, including zero.

    --
    MPI tutorial - learn parallel programming in C
    http://www.malcolmmclean.site11.com/www
     
    Malcolm McLean, Jan 24, 2012
    #13
  14. Mark

    Joe keane Guest

    In article <>,
    Malcolm McLean <> wrote:
    >All bits zero isn't necessarily a floating point zero, and it isn't
    >necessarily a null pointer. Which makes calloc() pretty useless.


    To be honest, i don't think it's a big problem. I have code where i
    simply 'memset' the whole struct, and i'm sure it's been ported to
    twenty machines. No one ever comes back and says 'i ran into that
    thing where you memset the struct, it didn't work'.

    So there's practical portable versus paranoid portable.

    It's something i just don't care about and i think is not worth spending
    your time on. My employer doesn't care i don't care because, while
    customers may have pretty diverse platforms, they're not geting stuff
    from bizarro world.

    Architectures can be different, but there really isn't much variation
    these days in how basic data types [integer, floating-point number,
    pointer] are stored [and how VM basically works].

    This is something that people were unsure about 40 years ago; now we
    'have the answer'. Such things seem sufficient obvious that you don't
    think about it much.
     
    Joe keane, Jan 24, 2012
    #14
  15. Malcolm McLean <> writes:

    > On Jan 23, 11:21 pm, Ben Bacarisse <> wrote:
    >>
    >> In systems where the mantissa is not normalised (i.e. there is no
    >> implicit leading 1) then zero is specified quite naturally with a zero
    >> mantissa.  A zero sign bit and exponent (even it biased) makes no
    >> difference.  Systems like this are common: IEEE decimal floating point
    >> and IBM's hexadecimal floating point come to mind.
    >>

    > So how does the processor do equality comparisons, efficiently?
    >
    > If the mantissa is not normalized then there are many possible
    > representations for each number, including zero.


    I am not 100% sure I have the terminology right. The mantissa may be
    normalised in the sense of having no redundant leading zero digits but
    in the systems I am describing (ones that don't use binary) there can't
    be an implicit leading digit. A normalised binary mantissa always
    starts 0.1... so such system don't bother to store the leading 1. As a
    result, zero can't be represented with a zero mantissa. On systems with
    non binary digits, the leading digit can't be omitted so a zero
    mantissa represents zero no matter what the exponent is.

    I can't answer your question about efficient equality testing -- you'd
    have to ask a hardware designer. However, the fact that there are
    redundant representations should not be a surprise. I don't know any FP
    format that does not have multiple representations that must compare
    equal (+0 and -1 being the most common example).

    --
    Ben.
     
    Ben Bacarisse, Jan 24, 2012
    #15
  16. Ben Bacarisse <> writes:
    [...]
    > I can't answer your question about efficient equality testing -- you'd
    > have to ask a hardware designer. However, the fact that there are
    > redundant representations should not be a surprise. I don't know any FP
    > format that does not have multiple representations that must compare
    > equal (+0 and -1 being the most common example).


    I think you mean +0 and -0.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 24, 2012
    #16
  17. (Joe keane) writes:
    > In article <>,
    > Malcolm McLean <> wrote:
    >>All bits zero isn't necessarily a floating point zero, and it isn't
    >>necessarily a null pointer. Which makes calloc() pretty useless.

    >
    > To be honest, i don't think it's a big problem. I have code where i
    > simply 'memset' the whole struct, and i'm sure it's been ported to
    > twenty machines. No one ever comes back and says 'i ran into that
    > thing where you memset the struct, it didn't work'.
    >
    > So there's practical portable versus paranoid portable.
    >
    > It's something i just don't care about and i think is not worth spending
    > your time on. My employer doesn't care i don't care because, while
    > customers may have pretty diverse platforms, they're not geting stuff
    > from bizarro world.
    >
    > Architectures can be different, but there really isn't much variation
    > these days in how basic data types [integer, floating-point number,
    > pointer] are stored [and how VM basically works].
    >
    > This is something that people were unsure about 40 years ago; now we
    > 'have the answer'. Such things seem sufficient obvious that you don't
    > think about it much.


    There was a very similar attitude that assumed that dereferencing a null
    pointer would give you zero:

    int *ptr = NULL;
    int *result = *ptr; /* undefined behavior */
    assert(result == 0);

    because a very popular system happened to guarantee it. A whole lot of
    code broke when it was ported to a new system.

    There were similar assumptions expressed as "All the world's a VAX"; the
    more modern equivalent woudl be "All the world's an x86".

    Admittedly there's a more widespread basis for assuming that
    floating-point 0.0 and null pointers are represented as all-bits-zero --
    but they're still assumptions that are not supported by the standard.

    If it turns out that all existing implementatations happen to satisfy
    those assumptions, I wouldn't object to adding them as requirements in a
    future edition of the C standard. That's exactly what happened with the
    assumption that all-bits-zero is a representation of 0 for all integer
    types; standards up to and including C99 didn't make that guarantee, but
    it was added in one of the Technical Corrigenda and appears in the C11
    standard.

    Until and unless that happens, I'm not going to count on it -- or if I
    do, I'll add a prominent comment documention my assumptions, so future
    maintainers will know where to look if things break.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 24, 2012
    #17
  18. Malcolm McLean wrote:
    > So how does the processor do equality comparisons, efficiently?
    >
    > If the mantissa is not normalized then there are many possible
    > representations for each number, including zero.
    >
    > --
    > MPI tutorial - learn parallel programming in C
    > http://www.malcolmmclean.site11.com/www


    Usually one does an epsilon test.
    with epsilon rather small

    if(((a+epsilon)<b)&&((a-epsilon)>b))
    {

    }

    The following will most likely evaluate to false on intel machines
    The compiler just does a (bitwise)equality test.

    a=+0.0;
    b=-0.0;

    if(a==b)
    {

    }
     
    Johann Klammer, Jan 24, 2012
    #18
  19. Johann Klammer <1.net> writes:
    > Malcolm McLean wrote:
    >> So how does the processor do equality comparisons, efficiently?
    >>
    >> If the mantissa is not normalized then there are many possible
    >> representations for each number, including zero.

    >
    > Usually one does an epsilon test.
    > with epsilon rather small
    >
    > if(((a+epsilon)<b)&&((a-epsilon)>b))
    > {
    >
    > }


    That doesn't address the question, which is how the processor performs a
    floating-point equality test, the one specified by C's "==" operator.

    > The following will most likely evaluate to false on intel machines
    > The compiler just does a (bitwise)equality test.
    >
    > a=+0.0;
    > b=-0.0;
    >
    > if(a==b)
    > {
    >
    > }


    Only if the compiler is broken. "a==b" yields 1 if a and b are
    *numerically* equal, 0 if they're not. If two bit patterns represent
    the same value, bitwise comparison will not work.

    Oh, and "b=-0.0" won't set b to a floating-point negative zero.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 24, 2012
    #19
  20. Mark

    James Kuyper Guest

    On 01/24/2012 12:35 PM, Malcolm McLean wrote:
    > On Jan 23, 11:21 pm, Ben Bacarisse <> wrote:
    >>
    >> In systems where the mantissa is not normalised (i.e. there is no
    >> implicit leading 1) then zero is specified quite naturally with a zero
    >> mantissa. A zero sign bit and exponent (even it biased) makes no
    >> difference. Systems like this are common: IEEE decimal floating point
    >> and IBM's hexadecimal floating point come to mind.
    >>

    > So how does the processor do equality comparisons, efficiently?
    >
    > If the mantissa is not normalized then there are many possible
    > representations for each number, including zero.


    The case that I'm most familiar with, IEEE 754 double precision,
    sub-normal numbers have an exponent of 0, a sign bit, and 52 bits of
    mantissa, and represent the values (-1)^sign * mantissa* 2^(-1022-52).
    The smallest positive value that can be represented is 2^(-1074), the
    largest is 2^(-1022) - 2^(-1074).

    For normal numbers, 0<exponent && exponent < 0x7FF. The value
    represented is (-1)^sign*(1.mantissa)*2^(exponent - 1023). The smallest
    positive value represented by this mechanism occurs when mantissa is 0
    and exponent is 1, which represents 2^(-1022). That is exactly 2^-1074
    bigger than the biggest subnormal value.

    The exponent value 0x7FF is reserved for infinities and NaNs.

    There doesn't seem to be any overlap in the ranges of normal and
    subnormal values, and within each category, all of the non-zero values
    that can be represented have a unique representation. A value of exactly
    0 must have it's mantissa and exponent both zero, but can have it's sign
    bit either set or cleared. As a result, equality comparisons can be
    replaced by memcmp(), except for the special handling required by IEEE
    754 for +0, -0, infinities and NaNs.
    Within this scheme, could you provide an example of the "many possible
    representations for each number" that you're referring to?
     
    James Kuyper, Jan 24, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alan Seunarayan

    RegexAssembly?_0.dll and Zero-touch deployment

    Alan Seunarayan, Jun 5, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    1,201
    Alan Seunarayan
    Jun 6, 2004
  2. Zhiqiang Ye
    Replies:
    53
    Views:
    10,278
    Dan Pop
    Jun 28, 2004
  3. Gerard Flanagan
    Replies:
    3
    Views:
    448
    Terry Hancock
    Nov 19, 2005
  4. Christopher Benson-Manica

    Doubles and zero/negative zero

    Christopher Benson-Manica, Jun 30, 2004, in forum: C Programming
    Replies:
    4
    Views:
    680
    Walter
    Jul 1, 2004
  5. Christopher Pisz

    zero memory

    Christopher Pisz, Apr 5, 2007, in forum: C++
    Replies:
    25
    Views:
    1,107
Loading...

Share This Page