【问题标题】:When do we declare a pointer of an ADT in C and why?我们何时在 C 中声明 ADT 的指针,为什么?
【发布时间】:2019-07-22 11:38:47
【问题描述】:

通常当我们使用 C 中的关键字“struct”创建一个新结构时,我们可能会在源文件以外的其他文件中使用该结构,我们使用关键字“typedef”来定义指向该结构的指针;

typedef struct struct_name* StructName; // for exmaple

我们为什么不简单地这样定义它;

typedef struct struct_name StructName; // this time i am not using pointers

使用这两种方式有什么不同吗?

【问题讨论】:

  • 是的,它们是不同的,第一种形式通常被认为是不好的做法:typedef is evil,总是更喜欢第二种形式。
  • 永远不要在 typedef 后面隐藏指针类型,这只会造成混乱。
  • 不,最好不要为 ADT 定义这样的 指针。考虑 C FILE 这是一个结构 - 你在任何地方都使用 FILE *
  • “ADT”是什么意思?请阅读标签说明。标签 adt 是关于一个 Android 插件的。
  • @Jabberwocky 通常我会同意,当使用结构用户可以直接取消引用的普通结构时。但是对于只能通过一组 API 函数引用数据的不透明数据结构,我认为这并不重要。

标签: c pointers abstract-data-type


【解决方案1】:

针对指针的 typedef 的通用论点是,如果您使用表单

typedef struct struct_name *ADT;

你不能声明一个不修改数据结构的函数:

void some_function(const ADT bar);

表示struct struct_name *const bar,即指针不能指向不同的值,但可以修改指向的结构。如果你想这样做,那么你需要有 another typedef 用于常量类型:

typedef const struct struct_name *ConstADT;

void some_function(ConstADT bar);

很难意识到它们是同一类型但不同的资格。然后你很快就会有各种垃圾类型定义,比如LPCVOIDPTRCSTR,每个人都会头疼。

【讨论】:

    【解决方案2】:

    这个类型定义

    typedef struct struct_name* StructName;
    

    首先声明类型struct struct_name,其次声明类型struct struct_name*

    你也可以通过以下方式重写 typedef

    struct struct_name typedef  *StructName;
    

    要声明 StructName 类型的指针(与 struct struct_name* 相同),无需定义结构 struct_name。那就是struct struct_name的类型可能不完整。

    所以当你在某个编译单元中只需要一个结构类型的指针时,通常会使用这种方法。这里是StructNamestruct struct_name * 类型的别名。

    但是这种方法有一个缺点。例如如果你会写例如

    const StructName *pv;
    

    那不代表

    const struct struct_name *pv;
    

    那就是指针指向一个常量对象。

    这意味着指针本身是常量位而不是指向的对象。也就是等价于下面的声明

    struct struct_name * const pv;
    

    如果您需要声明struct struct_name 类型的变量,您必须编写(前提是已经定义了结构)

    struct struct_name v;
    

    但要声明指向结构对象的指针,您可以使用任一

    struct struct_name *pv;
    

    StructName pv;
    

    如果在编译单元中确实需要struct struct_name 类型的变量,这会使代码的读者感到困惑。

    这个类型定义

    typedef struct struct_name StructName;
    

    struct struct_name 类型引入别名StructName(而不是指向struct struct_name 类型对象的指针,因为它是在以前的typedef 上完成的)。

    在这种情况下,使用的类型名称将在编译单元中与 struct struct_name 类型的变量声明和指针声明保持一致

    struct struct_name v;
    struct struct_name *pv:
    

    【讨论】:

      【解决方案3】:

      最大的区别是第一个可以直接定义变量,而另一个不能。

      为简化起见,假设我们有两种不同的类型别名,一种用于指向结构的指针,另一种用于结构本身:

      typedef struct struct_name* StructNamePtr;
      typedef struct struct_name StructName;
      

      现在这是可能的:

      StructNamePtr my_pointer_1;
      StructName *my_pointer_2;
      

      但不是这个

      StructName my_struct;  // Will lead to error if `struct_name` truly is an opaque data
                             // structure, and not available to the compiler
      

      请注意,变量 my_pointer_2 的定义与您定义 FILE 流的方式非常相似,这是因为 C 库为此使用了相同的技术。

      【讨论】:

        猜你喜欢
        • 2014-02-17
        • 2021-07-13
        • 1970-01-01
        • 1970-01-01
        • 2017-06-22
        • 2017-01-05
        • 2017-06-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多