【问题标题】:How to check if a struct is NULL in C or C++如何在 C 或 C++ 中检查结构是否为 NULL
【发布时间】:2014-11-12 08:11:12
【问题描述】:

我有以下结构

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

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

感谢任何帮助

【问题讨论】:

  • 一般你不能。但是AnotherStruct 可以有一个名为empty 的字段,您可以检查一下。
  • Null-ness 仅适用于指针。恐怕您正在对源自 Java 甚至 C# 背景的 C++ 做出假设,但您将不得不忘记这些。顺便说一句:C 和 C++ 也是不同的语言,因此对一种语言的回答通常不适用于另一种语言,尽管这种情况是一个例外。
  • 视情况而定。它不是指针,因此不能为“null”。它可以是零填充的,但这并不意味着它也是空的,它只意味着它被零填充。我相信AnotherStruct 有一些属性可以用来检查它的有效性,如果不知道应该如何使用这个结构,就无法告诉你它是什么。
  • 当且仅当零填充结构表示空时,您可以使用“memcmp”,但正如其他评论者所建议的那样,应该有一种方法来检查结构是否有效/非空。
  • 您需要指定结构在“空”时的外观 - C/C++ 中的结构永远不会为空,它只是填充了或多或少定义明确的东西由您或设计它的人来决定解释。

标签: c++ c data-structures


【解决方案1】:

我发现自己处于与您(做过)类似的修复中。我需要对给定的结构进行打包,并且知道结构中的确切字节数将有助于我序列化结构。但是,某些结构是空的,因此序列化无法对齐确切的字节数。

虽然这是 3 年后的事,但我找到了以下对我有用的解决方案:

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

结果可查询为is_empty&lt;T&gt;::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;

以下是参考:

【讨论】:

    【解决方案2】:

    您需要一些方法将AnotherStruct stData 标记为空。

    • 首先检查(或仔细检查)与AnotherStruct 相关的文档和 cmets,可能会询问制作它的人是否可用,以了解是否有官方方法来做你想做的事。

    • 也许那个结构体有一个指针,如果是空指针,结构体就是空的。或者也许有一个整数字段,其中 0 或 -1 或其他东西可能意味着空。甚至是一个布尔字段来标记它为空。

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

    • 如果上述失败,请在MyData 中添加一个布尔字段,以判断stData 是否为空。

    • 您还可以解释data1 和/或data2 的某些值(例如,空字符串?充满0xFF 字节?)表示空stData

    • 如果您无法修改或重新解释任一结构的内容,则可以将空项和非空项放在不同的容器(数组、列表、任何您拥有的)中。如果MyData 项是从堆中一一分配的,那么这与a free list 基本相同。

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

    【讨论】:

    • 我不同意。要么实现者已经定义了一种将stData 标记为空的方法,然后只使用那种方式和那种方式。或者它并不意味着是空的,那就不要试图重新解释它的语义。
    • @ArneMertz 我看不出您的评论与我的回答有何不同。如果没有某种“空”状态或不需要这种状态,那么 OP 的问题就没有意义。第一个项目符号涵盖了它已经内置,最后两个项目符号涵盖了空结构本身没有意义的情况,即。有刚刚使用和未使用的条目。
    • @ArneMertz 并且除了实现者已经定义了一种方式,或者实现者意味着它不能为空之外,还有一些实现者没有想到的选项,需求发生了变化,或者实施者只是不知道他们在做什么......
    • @ArneMertz 我同意文档,作为新的第一个项目符号添加到答案中。但其余的......不幸的是,现实世界并非如此。能够丢弃例如一些库或一些遗留模块,然后从头开始,是一种并不总是可用的奢侈品。
    • @ArneMertz 据我了解,问题是关于如何编写将进入 包装器/适配器的代码。
    【解决方案3】:

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

    如果实现者选择不将stData 设为指针,那么是有原因的。他们会知道如何表达“stData 是空的”,如果它甚至被允许为空的话。您绝对应该尝试在文档中查找这些语义或与他们交谈。不要试图将自己的语义添加到具有特定目的和语义的结构中。

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

    【讨论】:

      【解决方案4】:

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

      struct x;
      int y;
      

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

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

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

      初始化时设置为真。

      【讨论】:

      • 这是关于解决方案的 C++ 不是吗?如果是这样,你应该说明它,否则:告诉我,因为什么时候 bool 对 c 很常见。 (不是_Bool)
      【解决方案5】:

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

      struct AnotherStruct {
          bool valid;
          char aother_data1[10];
          char aother_data1[10];
          //...
      };
      
      if (stData.valid==true){
          //do something
      }
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-05
          • 1970-01-01
          • 2017-06-16
          • 1970-01-01
          • 1970-01-01
          • 2020-10-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多