我们都知道如何在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,那么在第二行中,我就像是用成员重新声明它。
这一点的解释是什么?
答案 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的结构类型而不定义其内容。这通常是为了能够将变量声明为指针到结构类型。在定义之前,您不能声明实际结构类型的变量。