1

I have a static array in c defined like this:

typedef struct
{
int a;
int b;
int c;
int d;
} Hello;

static Hello hello[6] = {{0}}; 

then at some points I need to reset all the attributes of each elements in this static array to 0; how to do this?

unwind
  • 391,730
  • 64
  • 469
  • 606
  • The initial initalization (`={{0}}`) is unnessasary because it is `static`. If it is global, it is also initalized for you. – weston Nov 19 '12 at 12:03

2 Answers2

6

You need to use memset():

#include <string.h>
memset(hello, 0, sizeof hello);

Note that this only works since "all bits 0" is a pretty safe assumption for setting int variables to 0. If hello had contained e.g. floats or pointers, that assumption doesn't hold at all and you would have to do a manual loop.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Surely all bits zero is OK for pointers? equivilant of `NULL` isn't it? If not, then people could not write: `if(pointer)` for `if(pointer!=NULL)` – weston Nov 19 '12 at 11:45
  • @weston: no, it is not guaranteed to be OK for pointers. If the representation of a null pointer on the implementation is anything other than all bits zero, then the code that the compiler emits for `if (pointer != NULL)` will compare the pointer value against something other than all bits zero. Such implementations have existed, but you're unlikely to encounter one. – Steve Jessop Nov 19 '12 at 12:03
  • @SteveJessop Those implementations must be non-ANSI-C then: http://stackoverflow.com/questions/1284050/c-comparison-to-null – weston Nov 19 '12 at 12:28
  • @weston: no, they conform, that's what I meant by "it is not guaranteed". Nothing in the question you link to (or more importantly in the standard) says that the representation of NULL is all bits zero. – Steve Jessop Nov 19 '12 at 12:41
  • @SteveJessop It does say that: Suppose `NULL` were defined as a non-zero constant, and let a pointer `p=NULL;` then `if(!p)` will not work as expected. As `!a==0` where `a!=0` and `if(expression)` is defined as passing if and only if `expression` evaulates to non-zero. – weston Nov 19 '12 at 13:30
  • @weston: the standard does not say that. `if(!p)` *will* work as expected even if the code `p = NULL` results in `p` having a bit pattern that is not all zeros. It is the responsibility of the compiler to ensure that it does, but it is possible for the compiler to fulfill that responsibility without null pointers having an all-zero bit pattern. Possibly what you're missing is that the conversion from constant `0` to a pointer type, is permitted to change the bit pattern, and that `!p` is defined to be `1` if `p` is a null pointer and `0` if `p` is not a null pointer, regardless of the bits. – Steve Jessop Nov 19 '12 at 13:32
  • @SteveJessop Oh, so in effect this could happen: `!(int)p != !p` because the compiler does something special when it nots a pointer? – weston Nov 19 '12 at 13:37
  • @weston: the result of `(int)p` is implementation-defined. I don't *think* there's anything to prevent an implementation from defining that a null pointer converts to an integer other then `0`, but even if a null pointer has some bit-pattern other than all-bits-zero the implementation could still choose to define that `((int)p) == 0` if and only if `p` is a null pointer. If it defines otherwise then yes, you could have pointer values for which `!(int)p` is different from `!p`. – Steve Jessop Nov 19 '12 at 13:43
  • @SteveJessop Thanks for that, that's blown my mind for today! I also found such info here: http://c-faq.com/null/ptrtest.html Funny, my K&R second edition that link references section A.7.4.7 defines `!` as "result is 1 if the value of operand compares equal to 0, and 0 otherwise." same for pointer or int. But what it fails to mention is that pointer 0 may not be all zero bits. – weston Nov 19 '12 at 13:50
  • @weston: well, it is true that a pointer compares equal to the constant `0` if and only if it is null, because the `0` is converted to the pointer type for the comparison (resulting in a null pointer). So K&R is correct, it just isn't laying out all the obscure possibilities for what "compares equal to 0" might imply. – Steve Jessop Nov 19 '12 at 13:52
0

I disagree with unwind on the initilization of floats and pointers "that assumption doesn't hold at all" - well it holds most of the time.

It is pretty safe to assume float 0 is all zeros in my opinion, as you are likely to have IEEE 754 floats. See If all bits are 0, what is the value of IEEE floating point?

And it's pretty safe to assume a null pointer is zero i.e. NULL == 0. Although also not guaranteed.

If you want to make sure of these assumptions and prove that in your environment that memset is safe, then I propose the following:

void testFloatAssumptions()
{
    const float fzero=0;
    float f;
    memset(&f,0,sizeof(f));
    if(memcmp(&f,&fzero,sizeof(f))!=0)
    {
      //then you have a float problem w.r.t. memset(...,0,...)
    }
}

void testPointerAssumptions()
{
    const int* nullPointer=NULL;
    int* pointer;
    memset(&pointer,0,sizeof(pointer));
    if(memcmp(&pointer,&nullPointer,sizeof(pointer))!=0)
    {
      //then you have a pointer problem w.r.t. memset(...,0,...)
    }
}

The alternative is a lot of manual coding for situations which you are unlikely to come across.

Community
  • 1
  • 1
weston
  • 54,145
  • 21
  • 145
  • 203
  • @SteveJessop Given our conversation, I'd appreciate your oppinion on my take on when it's safe to use memset on pointers and floats. – weston Nov 19 '12 at 13:53
  • I agree with you that it's "pretty safe", and some C implementations explicitly guarantee it to avoid doubt. Your tests (if they pass) show that all-bits-zero does represent a null pointer / zero float. I think you're correct that if the `memcmp` returns 0 then it is safe to initialize pointers / floats with `memset`. – Steve Jessop Nov 19 '12 at 13:59
  • `NULL == 0` is always true regardless of the bit patterns, btw. `NULL` is either an integer constant with value 0 (in which case it's an integer comparison) or else it's a null pointer with type `void*` (in which case it's a pointer comparison and the `0` on the RHS is converted to a null pointer first). – Steve Jessop Nov 19 '12 at 14:14