【问题标题】:Empty struct typedef空结构类型定义
【发布时间】:2014-05-28 21:05:57
【问题描述】:

这是一个家庭作业问题:

该项目的目标是为 void * 数据类型实现双链表。

我得到了一个具有以下结构定义的 .h 文件:

//dlList.h
#ifndef _DLLIST_ADT_H_
#define _DLLIST_ADT_H_

#include <stdbool.h>

#ifndef _DLL_IMPL_

/// DlList_T points to a representation of a double-linked list 
/// of void pointers (to abstract data objects).
typedef struct { } * DlList_T;

#endif

//Function declarations below

#endif

在我的 dlList.c 文件中,我正在尝试做这样的事情:

//dlList.c

typedef struct _dlNode{

    struct _dlNode *prev;
    struct _dlNode *next;
    void * data; //pointer to a memory address

} dlNode;

struct _DlList_T{

    struct _dlNode *start; //the first item in the list
    struct _dlNode *cursor; //the current item the list is pointing to
    int curIndex; //index of current item
    int maxIndex; //number of items in list


} * DlList_T;

//Rest of .c file 

我所有的错误都与

的变体有关

“DlList_T”的类型冲突

我已经尝试了 .c 文件中结构的几种变体,但我认为我遗漏了一些非常明显的东西......

我是否应该将我的 DlList_T 结构放入我的 .c 文件中,将其重命名为其他名称,然后在需要时将其转换...?

另外请注意,我不允许以任何方式更改 .h 文件。当我提交项目时,try 将使用 .h 文件的本地副本。

我很迷茫,任何帮助将不胜感激,谢谢!

编辑:包含头文件的#ifndef 和#endif

编辑 2:这是使用 gcc 使用 -std=c99 标志编译的。

【问题讨论】:

  • 您是否需要在 .c 文件中定义 DlList_T ? (您是否需要使用 .h 文件中的 DlList_T 结构?)
  • 空的 struct 在标准 C 中是非法。(某些编译器可能支持也可能不支持它作为扩展。)
  • @Mahonri 不确定,但我相信是这样。头文件中的一个示例函数是void dll_clear( DlList_T lst );,所以我认为它必须有一些声明。我还编辑了我的原始问题以包含 #ifndef 和 #endif 标签。
  • @Keith 我们使用的是标准的 gnu c 编译器,如果这有影响的话。
  • gcc 不严格遵循标准,除非你告诉它,比如-std=c99 -pedantic。 gcc 恰好支持空结构作为扩展,但我不建议依赖它,除非你有一个 very 很好的理由这样做。该评论谈到“空指针的双链表”;你可能需要在你的结构中有一个void* 成员。

标签: c struct void-pointers


【解决方案1】:
#include <dlList.h>

typedef struct _dlNode
   {
   struct _dlNode *prev;
   struct _dlNode *next;
   void * data; //pointer to a memory address
   } dlNode;

struct _MyList_T
   {
   struct _dlNode *start; //the first item in the list
   struct _dlNode *cursor; //the current item the list is pointing to
   int curIndex; //index of current item
   int maxIndex; //number of items in list
   } * MyList_T;

void dll_clear(DlList_T lst)
   {
   MyList_T list = (MyList_T)lst;

   list->cursor...

   return;
   }

【讨论】:

  • 谢谢!这是有效的,我认为这是正确的实施。明天上课的时候我会和他再确认一下。作为旁注而不是做MyList_T list = (MyList_T*)lst;,我不得不将它分成两行并删除*以删除警告initialization from incompatable pointer type [enabled by default]。我认为这是因为 lst 已经是一个指针,而您的版本给了我一个 **...?
  • 糟糕...抱歉。我不得不做一个更正。当我应该将其转换为 (MyList) 时,我将列表值转换为 (MyList_T *)。
  • 此代码仍有一行 typedef struct { } * DlList_T; 处于活动状态。我不知道,你不可能在每个编译器中都编译这个,就像使用语言 C?? 而不是 C,非标准,随便......
  • @ThoAppelsin 这是使用带有 -std=c99 标志的 gcc 编译的。我知道这不是真正的香草 C,但也不是 for 循环。
  • -1:这鼓励类型转换并且不可移植。 OP 正在学习 C,并且已经被引入到 C 的丑陋角落,在这种特定情况下可能会碰巧工作,但整体生成的代码很难维护,答案甚至没有提到空结构的使用不是标准的 C.
【解决方案2】:

根据您的最新更新,考虑进行以下操作:

...

#define _DLL_IMPL_
// This is to prevent dlList.h from making that illegal thing

typedef struct _dlNode {

    struct _dlNode *prev;
    struct _dlNode *next;
    void * data; //pointer to a memory address

} dlNode;

typedef struct _DlList_T {

    struct _dlNode *start; //the first item in the list
    struct _dlNode *cursor; //the current item the list is pointing to
    int curIndex; //index of current item
    int maxIndex; //number of items in list

} * DlList_T;

#include "dlList.h"

...

或者类似的东西。确保DlList_T 已在.h.c 文件中使用之前,已被类型定义为有效结构。由于您不能违反.h 文件,因此您可能应该在包含它之前立即执行此操作。

您似乎最有可能被要求通过使用适当的预处理器指令(在本例中为#define _DLL_IMPL_)来防止进行这种非法的类型定义

【讨论】:

    【解决方案3】:

    我建议将列表节点的结构定义包含在头文件中,但您不能修改它,必须将其放在.c 源文件中。

    您的错误表明您对DlList_T 类型有多个定义:您不能说DlList_T 是空结构(您在标头中执行)的类型别名并且具有相同的类型指向struct _DlList_T 的指针(您在源文件中执行此操作)。

    所以,第一步:首先为列表变量选择另一个名称,例如,dbl_list

    struct _DlList_T {
    
        struct _dlNode *start; //the first item in the list
        struct _dlNode *cursor; //the current item the list is pointing to
        int curIndex; //index of current item
        int maxIndex; //number of items in list
    
    
    } *dbl_list;
    

    使用前导 _ 定义结构也是一个坏主意,因为这些结构是为实现保留的 - 考虑选择其他名称。

    头文件应该有这个:

    typedef struct DlList *DlList_T;
    

    或类似的东西(可能具有不同的结构标记)。您显示的代码不是标准 C(空结构不是标准),这没有任何意义。如果这是您的说明所提供的,我认为您应该将其报告为错误。或者,确保完成课堂练习——也许你应该使用一个特定的编译器,它带有支持这种结构的扩展。但请注意,它不是便携式的。

    【讨论】:

      【解决方案4】:

      您的第一个错误是 DlList_T 是 .h 文件中的类型和 .c 文件中的变量。这行不通。

      第二,你不应该有

      typedef struct { } * DlList_T;
      

      在 .h 文件中,但是

      typedef struct DlList * DlList_T;
      

      或类似的东西。这称为前向声明(对于两个不同的名称,struct DListDlist_T

      然后在 .c 文件中使用 {}struct Dlist 进行声明。这就是在 C 中隐藏类型细节的工作原理。如果你的导师真的给了你一个在头文件中带有{} 的版本,他或她应该在教给其他人之前先修改基本的 C。 (空 struct 在 C 中是违反约束的,但可能被 gcc 接受为扩展。)

      【讨论】:

      • 我得到了原始问题中描述的 .h 文件。我会将您直接链接到 .h 文件,但它在我的大学服务器上的密码后面。
      • 然后看我回答的第二部分:(对不起,如果是这样,你的问题没有有效的解决方案。
      • @OmegaTwig 那么您的讲师需要先学习 C,然后再尝试教授它。将此报告为项目分配中的错误,并引用 C 标准作为官方和可信来源。
      【解决方案5】:

      你从这句话开始

      typedef struct { } * DlList_T;
      

      其中typedefs 和空结构为DlList_T 的标识符。


      然后,稍后会出现这种情况

      struct _DlList_T{
      
          struct _dlNode *start; //the first item in the list
          struct _dlNode *cursor; //the current item the list is pointing to
          int curIndex; //index of current item
          int maxIndex; //number of items in list
      } * DlList_T;
      

      这又是typedefs 相同的标识符DlList_T。这是非法的。

      【讨论】:

        猜你喜欢
        • 2011-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-28
        • 1970-01-01
        • 2019-01-03
        • 1970-01-01
        相关资源
        最近更新 更多