声明结构:typedef struct name name;

时间:2015-05-23 21:17:16

标签: c struct typedef

我们都知道如何在C中声明一个结构:

struct Label1{ /* variables */ } Label2; // As I learned

但我想知道为什么这段代码在没有声明'struct name'的情况下有效:

typedef struct name s_name;

或者实际上是输入代码

struct name;

是否意味着我将'struct name'声明为void结构或类似的东西?

代码示例:

typedef struct Data Data;
struct Data{ /*variables*/ };

如果在第一行中将struct Data声明为void,那么在第二行中,我就像是用成员重新声明它。

这一点的解释是什么?

2 个答案:

答案 0 :(得分:9)

类似的东西:

struct MyStruct;

被称为前向参考。它创建了一个不完整的类型,告诉编译器会有一个类型的名称(它是一个结构 - 它对于联合同样有效),细节"后面跟随"。在完成类型之前,您无法定义变量。

typedef struct MyStruct MyType;

只需将类型名称定义为该结构。这仍然是一个不完整的类型。

但是,您可以使用指向不完整类型的指针:

MyType *my_t_pointer;
struct MyStruct *my_s_pointer;

当你提供完整的声明时,这对于一个struct指向同一类型的对象很有用,"完成"类型:

struct MyStruct {
    struct MyStruct *next;
};

实际上,这是为列表,树和所有其他递归数据结构创建节点的唯一方法。这是C程序的主要部分(有时是隐藏的)。

此外,此机制用于隐藏实现细节。标头中的函数只需知道存在的结构来接受/传递指针。使用这些函数不需要知道结构的细节(但是这样它不能分配它,因此模块必须涵盖需要知道结构细节的所有方面)。完整声明仅在模块的实现文件中。 这些指针被称为"不透明"因为人们不能通过"查看",即访问结构的字段,因为它们根本不为人所知。

my_module.h:

struct MyStruct;

extern void my_init(struct MyStruct *obj);

my_module.c:

struct MyStruct {
    int f1;
    ...
};

my_init(struct MyStruct *obj)
{
    ...
}

答案 1 :(得分:2)

typedef将s_name声明为struct name的别名,以便您可以声明变量,例如:

namespace library{

    namespace componentB{

       using componentA::SomeOtherClass;

       template<typename T>
       SomeOtherClass{
           void Foo(const Someclass<T>& reference);
           void Bar(const Someclass<T>& reference);
           void FooBar(const Someclass<T>& reference);
           void FooWithBar(const Someclass<T>& reference);
       };
    }

}

该行

    var recordID = new CKRecordID("diary");
    AppleHelper.PrivateDatabase.FetchRecord(recordID, (record, err) => {

    // Was there an error?
    if (err != null) {
        Console.WriteLine(err.ToString());
        Console.WriteLine("creating file...");

        var dbName = "diary.db";
        var dbPath = Path.Combine(documents.Path, dbName);
        AppDelegate.lib.Conn = new SQLite.SQLiteConnection (dbPath);
        AppDelegate.lib.Conn.CreateTable<LibChemotherapie.Diary> ();

        if (File.Exists (dbPath)) {

            var assetRecord = new CKRecord ("sqlite");
            var db = new CKAsset(NSUrl.CreateFileUrl(new string[] { dbPath }));
            assetRecord ["diary"] = db;

            AppleHelper.PrivateDatabase.SaveRecord (assetRecord, (record2, err2) => {

                if(err2 == null)
                    Console.WriteLine("uploaded");

            });

        }
    }
    else {

        Console.WriteLine("yeah exists");

    }
    });

声明存在名为name的结构类型而不定义其内容。这通常是为了能够将变量声明为指针到结构类型。在定义之前,您不能声明实际结构类型的变量。