nubela
nubela

Reputation: 17284

How to check if structs are initialised or not

typedef struct dict_pair {
  void *key;
  void *value;
  struct dict_pair *head;
  struct dict_pair *tail;
} dict;

dict* NewDictionary(void) {
  dict *dictionary = malloc(sizeof(dict_pair));
  dictionary->head = null;
  dictionary->tail = null;
}

int main(void) {
  dict *dictionary = NewDictionary();
}

I had initially planned to set the structs as null but the compiler does not allow it. How can I check if a struct is assigned or not?

Also, can I refer recursively declare the same struct inside the struct?

Upvotes: 4

Views: 12616

Answers (5)

RatDon
RatDon

Reputation: 3543

I'm using a trick which is working for me.

struct hello{
    ....;
    ....;
    ....;
};

struct hello *t;

t=malloc(sizeof(struct hello));
free(t);
t=NULL;

Now u can easily check if t is initialized or not. And there is no memory leak at all.

Upvotes: 0

Christoph
Christoph

Reputation: 169563

I'd use a statically allocated variable for initialization:

dict* NewDictionary(void) {
  static dict null_dict; // no initializer, so zero by default
  dict *dictionary = malloc(sizeof *dictionary);
  *dictionary = null_dict;
  return dictionary;
}

This guarantees that member are correctly zeroed, regardless whether they're pointers, floating point or integer types.

Upvotes: 1

Ed Carrel
Ed Carrel

Reputation: 4254

You can set them as NULL, but not as null. C is case-sensitive, and the NULL constant is all caps.

And to answer your second question, yes, struct definitions can be recursive in a sense. The internal reference has to be a pointer to the struct, instead of a straight definition of the struct. If the latter was allowed, you would end up with an infinitely recursing struct definition, which would be a bad thing. See Chris Lutz's answer for more details.

Upvotes: 0

Chris Lutz
Chris Lutz

Reputation: 75389

C doesn't have null, it has NULL. So try this:

dict* NewDictionary(void) {
  return calloc(sizeof(dict)); 
}

This fixes a few problems:

  1. You were leaving value and key uninitialized, so they could hold random garbage. Using calloc() will initialize everything to 0, which in pointer context is NULL. It won't even take that much more processing time.
  2. You weren't returning anything. This is undefined behavior. If you function ends without a return statement, it's only by sheer luck that anything will be returned.
  3. You were using dict_pair instead of struct dict_pair. In C++, struct names are in the regular type namespace, i.e. t x = { 0 }; is valid C++, but in C you'd need to say struct t x = { 0 };.
  4. You weren't checking the return value of malloc() (now calloc() but same rules apply). If there isn't enough memory, calloc() returns NULL. I'd hate to dereference a NULL pointer on accident. We don't have to check the return value here because I've done away with all the intermediate steps - calloc() is enough for us.

Note that calloc() is slightly less portable. Even though the standard does require that void *p = 0 sets the pointer to a null pointer, it doesn't require that the null pointer be "all bits set to zero", which is what calloc() technically does. If you don't want to use calloc() for this reason, here's a version that does the same thing with malloc():

dict* NewDictionary(void) {
  dict *dictionary = malloc(sizeof(dict)); 
  if(dictionary) {
    dictionary->head  = NULL;
    dictionary->tail  = NULL;
    dictionary->value = NULL;
    dictionary->key   = NULL;
  }
  return dictionary;
}

Or:

dict* NewDictionary(void) {
  dict *dictionary = malloc(sizeof(dict)); 
  if(dictionary == NULL) return NULL;
  dictionary->head  = NULL;
  dictionary->tail  = NULL;
  dictionary->value = NULL;
  dictionary->key   = NULL;
  return dictionary;
}

See how much nicer the calloc() version is?

As to your second question:

Also, can I refer recursively declare the same struct inside the struct?

No, you can't do this:

struct t {
  struct t x;
}

But you can do this (which is what you're doing, and what you want):

struct t {
  struct t *x;
}

You can have a pointer to a struct inside the struct itself, but you can't have the actual struct inside the struct itself. What you're doing is perfectly legal, because you're using pointers.

Upvotes: 8

user3458
user3458

Reputation:

You may want to consider calloc rather than malloc.

calloc fills the memory it allocates with 0s, so you'll have your head and tail as NULL w/o explicit assignment.

Upvotes: 1

Related Questions