简体   繁体   English

如何检查结构是否已初始化

[英]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. 我最初计划将结构设置为null,但编译器不允许它。 How can I check if a struct is assigned or not? 如何检查结构是否已分配?

Also, can I refer recursively declare the same struct inside the struct? 另外,我可以在结构中以递归方式声明相同的结构吗?

C doesn't have null , it has NULL . C没有null ,它有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. 你留下的valuekey未初始化,所以他们可以随机垃圾。 Using calloc() will initialize everything to 0, which in pointer context is NULL . 使用calloc()会将所有内容初始化为0,在指针上下文中为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. 如果你的函数在没有return语句的情况下结束,那么只有通过运气才会返回任何内容。
  3. You were using dict_pair instead of struct dict_pair . 您使用的是dict_pair而不是struct dict_pair In C++, struct names are in the regular type namespace, ie tx = { 0 }; 在C ++中, struct名称在常规类型命名空间中,即tx = { 0 }; is valid C++, but in C you'd need to say struct tx = { 0 }; 是有效的C ++,但在C中你需要说struct tx = { 0 }; .
  4. You weren't checking the return value of malloc() (now calloc() but same rules apply). 您没有检查malloc()的返回值(现在是calloc()但适用相同的规则)。 If there isn't enough memory, calloc() returns NULL . 如果内存不足, calloc()将返回NULL I'd hate to dereference a NULL pointer on accident. 我不想在事故中取消引用NULL指针。 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. 我们不必在这里检查返回值,因为我已经废除了所有中间步骤 - calloc()对我们来说已经足够了。

Note that calloc() is slightly less portable. 请注意, calloc()可移植性稍差。 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. 尽管标准确实要求void *p = 0将指针设置为空指针,但它并不要求空指针“将所有位设置为零”,这就是calloc()技术上的作用。 If you don't want to use calloc() for this reason, here's a version that does the same thing with malloc() : 如果由于这个原因你不想使用calloc() ,这里有一个与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? 看看calloc()版本有多好?

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. 你可以有一个指向 struct的内部struct本身,但你不能有实际的struct内部struct本身。 What you're doing is perfectly legal, because you're using pointers. 你正在做的事情是完全合法的,因为你正在使用指针。

You may want to consider calloc rather than malloc. 您可能想要考虑calloc而不是malloc。

calloc fills the memory it allocates with 0s, so you'll have your head and tail as NULL w/o explicit assignment. calloc用0分配它分配的内存,所以你的头和尾都是NULL,没有明确的赋值。

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. 这可以保证成员被正确归零,无论它们是指针,浮点还是整数类型。

You can set them as NULL , but not as null . 您可以将它们设置为NULL ,但不能为null C is case-sensitive, and the NULL constant is all caps. C区分大小写, NULL常量全部为大写。

And to answer your second question, yes, struct definitions can be recursive in a sense. 回答你的第二个问题,是的, struct定义在某种意义上可以是递归的。 The internal reference has to be a pointer to the struct , instead of a straight definition of the struct . 内部参考必须的指针struct ,代替的直定义struct If the latter was allowed, you would end up with an infinitely recursing struct definition, which would be a bad thing. 如果后者被允许,你最终会得到一个无限递归的struct定义,这将是一件坏事。 See Chris Lutz's answer for more details. 有关详细信息,请参阅Chris Lutz的答案。

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. 现在你可以很容易地检查t是否被初始化。 And there is no memory leak at all. 并且根本没有内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM