簡體   English   中英

為什么可以為不存在的結構創建 typedef?

[英]Why can you create typedefs to a struct that doesn't exist?

以下代碼編譯良好。

header.h:

typedef struct Placeholder_Type* Placeholder;

實現.cpp:

#include "header.h"

void doSomething(Placeholder t) {
  (void) t;
}
    
int main() {
  int *a = new int();
  doSomething((Placeholder)a);
}

編譯命令:

clang++ impl.cpp

Placeholder_Type 類型在任何地方都不存在,並且在 output 二進制文件中不作為符號存在。

為什么為不存在的類型創建 typedef 是合法的?

為什么我可以使用不存在的類型創建 function?

這是否等同於僅使用 void* 但命名為“占位符”?

struct Placeholder_Type聲明 struct Placeholder_Type (但沒有定義它),無論它出現在哪里。 即使它在typedef中。 因此,您不會為不存在的結構創建 typedef,而是為您剛剛聲明的結構創建 typedef(如果編譯器還不知道它,則創建它)。

至於為什么,因為這樣可以讓結構的定義遠離公共接口。 例如,這是在 C 中實現不透明 object 的典型方法:

// mytype.h
typedef struct MytypeImpl* Mytype;

Mytype create_mytype();
void destroy_mytype(Mytype o);

void do_something_with_mytype(Mytype o, int i);

// mytype.c
struct MytypeImpl {
  int something;
  int otherthing;
};
Mytype create_mytype() {
  Mytype o = malloc(sizeof(*o));
  o->something = 0;
  o->otherthing = 0;
  return o;
}
void destroy_mytype(Mytype o) {
  free(o);
}
// etc.

當然,個別 styles 可能在細節上有所不同。 但關鍵是結構的定義在 mytype.c 之外是不可見的,所以沒有人可以訪問數據成員。

為什么不? 據我所知,“存在”不是一個官方術語。 類型可以聲明但不定義,也可以聲明和定義。 在第一種情況下,類型被認為是不完整的。 對於不完整的類型,您無能為力。 例如,您不能創建該類型的對象。 但是,您可以使用指向不完整類型的指針。 編譯器需要知道的只是類型的聲明。 進一步注意 typedef 確實包含Placeholder_Type的聲明:

typedef struct Placeholder_Type* Placeholder; 
        ^---------------------^ declares the class named Placeholder_Type

在您的代碼中,您永遠不會創建 object 或使用它編譯的Placeholder_Type成員。 我不是 100% 確定,但我認為也沒有 UB。 強制轉換int看起來不太好,但是由於您從未真正取消引用指針,因此沒有任何問題。

有關更多信息,請參閱有關前向聲明的非常相關的問題: C++ 中的前向聲明是什么? 我什么時候可以使用前向聲明?

並非所有聲明都是同時定義。

例如,您可以聲明尚未定義的 function

void func( void );

然后引用名稱func

或者您可以聲明一個 class 例如

class A
{
    friend class B;
    //...
};

聲明在給定的 scope 中引入名稱。

只有在評估上下文中使用名稱時,它必須被定義並具有完整的類型。

在這份聲明中

typedef struct Placeholder_Type* Placeholder;

引入了兩個名稱: Placeholder_TypePlaceholder Placeholder 是指針類型struct Placeholder_Type*的別名。 指針類型的對象總是完整的對象。 您可以使用表達式計算其大小

sizeof( Placeholder )

這與擁有指向類型void的指針相同。

void *p;

void 類型始終是不完整類型,因為指針類型本身就是完整類型。 如果您不嘗試取消引用指針或應用指針算術,則引用類型不需要是完整的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM