问题 如何在C或C ++中检查结构是否为NULL


我有以下结构

typedef struct 
{
   char      data1[10];
   char      data2[10];
   AnotherStruct  stData;
}MyData;

由于某种原因,实现者选择不将stData作为指针,所以我必须忍受它。 我的问题是如何检查stData成员是否为空?因为如果它是空的我需要跳过我的代码中的某些东西。

任何帮助表示赞赏


10248
2017-09-18 05:44


起源

一般来说,你不能。但 AnotherStruct 可以有一个叫做的领域 empty,你可以检查一下。 - juanchopanza
Null-ness仅适用于指针。我担心你会对源自Java甚至C#背景的C ++做出假设,但你必须忘掉那些。顺便说一句:C和C ++也是不同的语言,所以一个答案通常不适用于另一个,尽管这种情况是个例外。 - Ulrich Eckhardt
这取决于具体情况。它不是指针,因此它不能为“null”。它可以是零填充但它并不意味着它也是空的,它只意味着它充满了零。我相信有一些属性 AnotherStruct 你用它来检查它的有效性,如果不知道如何使用这个结构,就没有办法告诉你它是什么。 - Havenard
当且仅当零填充结构意味着为空时,您可以使用'memcmp',但正如其他评论者所建议的那样,应该有一种方法来检查结构是否有效/非空。 - bkausbk
你需要指定结构在“空”时的样子 - C / C ++中的结构永远不会是空的,它只是充满了或多或少定义好的东西,这取决于你或者那个人设计它来确定解释。 - Anders


答案:


你需要一些方法来标记 AnotherStruct stData 空。

  • 首先检查(或仔细检查)与之相关的文档和注释 AnotherStruct,如果有可能的话,可能会问那些制作它的人,找出是否有正式的方法来做你想做的事。

  • 也许该结构具有指针,如果它是空指针,则结构为空。或者可能有一个整数字段,其中0或-1或某些东西可能意味着为空。甚至是一个布尔字段将其标记为空。

  • 如果没有上述任何一项,也许你可以添加这样一个字段,或者对某些字段进行这样的解释。

  • 如果上面的失败,请添加一个布尔字段 MyData 告诉你是否 stData 是空的。

  • 您还可以解释一些值(例如,空字符串?Full 0xFF byte?) data1 和/或 data2 意思是空的 stData

  • 如果你不能修改或重新解释任何一个struct的内容,那么你可以将空和非空项放在不同的容器中(数组,列表,无论你有什么)。如果 MyData 项目是从堆逐个分配,然后这基本上与具有相同 一个免费清单

  • 上面的变化,如果你有一个空的和非空的项目都混合在一个容器中,那么你可以有另一个容器 指针 或索引到非空项目(或空项目,或任何适合您的需要)。这有一个额外的复杂性,你需要保持两个容器同步,这可能是也可能不是微不足道的。


8
2017-09-18 05:53



我不同意。实现者已经定义了一种标记方法 stData 为空,然后只使用那种方式。或者它不是空的,然后不要试图重新解释它的语义。 - Arne Mertz
@ArneMertz我不明白你的评论如何不同意我的回答。如果没有某种“空”状态或需要这种状态,那么OP的问题就没有意义。第一个子弹覆盖它已经内置,两个最后的子弹覆盖空结构的情况本身没有意义,即。只是使用和未使用的条目。 - hyde
@ArneMertz除了已经定义了一种方式的实现者,或者实现者意味着它不能为空之外,还有实现者没有想到的选项,需求已经改变,或者实现者只是不知道他们在做什么...... - hyde
@ArneMertz我同意文档,作为新的第一个子弹添加到答案中。但其余的......不幸的是,现实世界并不像那样。能够抛弃一些库或一些传统模块,并从头开始,这是一种并不总是可用的奢侈品。 - hyde
@ArneMertz据我所知,问题是关于如何编写将会发生的代码 成 包装器/适配器。 - hyde


如果它不是指针,则在创建对象MyData时将分配结构成员的内存。当您定义结构时,使用calloc或memset将它们全部设置为零,然后您可以比较为0


1
2017-09-18 05:53





你可以找到一些标志变量。恩。

struct AnotherStruct {
    bool valid;
    char aother_data1[10];
    char aother_data1[10];
    //...
};

if (stData.valid==true){
    //do something
}

1
2017-09-18 06:40





我发现自己和你一样(确实)。我需要打包一个给定的结构,并知道结构中的确切字节数将帮助我序列化结构。但是,某些结构为空,因此序列化无法对齐确切的字节数。

虽然这是3年后,我发现以下解决方案对我有用:

template <typename T> struct is_empty {
    struct _checker: public T { uint8_t dummy; };
    static bool const value = sizeof(_checker) == sizeof(T);
};

结果可以查询为 is_empty<T>::value 并在编译时可用。

template <typename S>
typedef union {
    struct __attribute__((__packed__)) {
        ObjId   id;
        S       obj;
    } dataStruct;
    std::array<uint8_t, (sizeof(dataStruct) - is_empty<S>::value)> byteArray;
} _msg_t;

以下是参考资料:


1
2018-02-26 20:27





Struct是用户定义的类型,因为int是内置类型的。

struct x;
int y;

首先尝试回答“如何确定你的int是否为空,或者在首次声明之后没有”

关于解决方案: - 如果你想知道它的初始化是否是这样的话,请以这种方式使用你的结构: -

struct X
{
  bool b;
  X() : b(false) {}  
};

初始化时将其设置为true。


0
2017-09-18 07:07



这是关于解决方案的C ++不是吗?如果是这样,你应该说出来,否则:告诉我,因为当bool常见于c时。 (不是_Bool) - dhein


我假设结构定义是某些第三方功能/库的一部分,其中第三方可能是您自己公司内的某个人。

如果实施者选择不做 stData 一个指针,然后有原因。他们会知道如何表达“stData 是空的“,如果它甚至被允许为空。你一定要尝试在文档中查找那些语义或与它们交谈。不要试图将自己的语义添加到具有特定目的和语义的结构中。

所以,如果有  表达结构部分的预定义方式是空的,使用这种方式。如果它的用途可能不是空的,那么不要试图使其为空。简而言之,不要以不打算使用的方式使用类/结构。相反,如果您发现自己只有“MyData”所需的部分数据才有意义,那么编写自己的“MyPartialData”结构来处理这种情况并将其转换为“MyData”一旦您拥有所需的一切并准备好与第三方API进行交互。


0
2017-09-18 08:11