声明在C类专用结构

问题描述 投票:2回答:4

是否有可能声明结构类型,它是唯一可见在使用结构中.c文件?我知道,通过把静态的外部数据对象的面前,你改变变量的联动,是内部的。但是,它可能把静中有新的结构类型的声明前,如下所示?

static struct log{
            ...;
            ...;
};
typedef struct log log;

如果它是不可能使结构类型,比如说如上日志,是“私人”,这是否意味着即使其他源文件不知道名字的存在(这是在我的例子日志)结构的如果他们说出一些变量日志(假设我将链接所有目标文件)意外的名称冲突仍然发生呢?

编辑:我不熟悉的编译器/连接器是如何工作的。如果有一个全局变量名的日志,并包含全局变量与在结构日志定义的唯一来源文件的文件,也不会引起任何混乱链接时,一个日志,而另一个日志中的变量名是一种叫什么名字?

c struct private
4个回答
8
投票

号作出struct私人唯一的办法是只在使用它的文件中提供的定义 - 不要把它放在一个公共的头文件。如果它在一个源文件中只使用,那么只需把它定义在源文件中,但如果它在多个源文件中使用,你有一个棘手的问题:你可以在每一个源文件中定义它,但这是脆弱的,因为你有要记住,当你做任何改变来改变它的每一个实例;或者,你可以在私人头文件中定义它,并确保只有那些源文件包括私有头。

在不同的源文件名冲突是正常的,只要他们不试图以任何方式相互连接。如果你在一个文件中,并在不同的文件struct log的不同定义所定义的struct log,永远不要通过一个log到其他。在C语言中,结构的名字不会成为目标文件中的任何符号名称的一部分 - 尤其是有函数名称没有名称重整包括的参数类型(如C ++一样),因为函数重载是非法C.


2
投票

static是存储型;这是没有意义的将其应用到一个类型的变量声明之外。

如果你不想来定义你的头文件struct log,你不必。简单地写的typedef为:

typedef struct log log;

就足够了,只要你只log *指针处理。但是,您将需要结构的完整定义来声明log(或采取sizeof(log)),由于结构的大小取决于它所包含的内容。

对于名称冲突,记住,结构和类型不通过链接进行管理。链接器只关心全局可见的符号,如函数和变量。话虽这么说,你应该申请一个前缀为您的类型名称(例如,mylib_log_t),以避免混淆,特别是因为log是在标准库数学函数。


0
投票

你有理由这样写:

static int a;

因为它防止连接器将其与定义的其他地方a结合。 该连接器具有无关structs,所以没有后顾之忧投入不同的C文件。 只要它在不同的C文件,会出现没有名字混淆。


0
投票

这是不可能的一般。但我可以认为这可能对一些编译器工作黑客攻击的。

之所以这样,是很难做到是因为C编译器需要知道的结构是什么样子,以产生与结构参数的情况下调用功能。

因此,假设您定义与下面的头一库:

struct foo {
    int32_t a, b;
};

foo make_foo(int arg);

foo do_something(foo p1, foo p2);

然后编译程序,这使得调用do_something,编译器通常需要知道结构foo是什么样的,所以它可以把它作为一个参数。编译器可以做各种奇怪的事情在这里,就像通过堆栈通过寄存器和部分传递结构的一部分,所以它真正需要知道的结构是什么样子。

但是,我认为,在一些编译器,可以给其结构应通过堆栈完全传递的指示。例如,regparm(0)功能属性应海湾合作委员会的工作,如果你已经I386作为你的目标体系(docs)。

在这种情况下,它应该可以做这样的事情:创建头文件的“公版”,并在该文件中,而不是摆出完整的结构,你创建它的一个未分化的版本:

struct foo {
    uint8_t contents[SIZE_OF_STRUCT_FOO];
}

其中SIZE_OF_STRUCT_FOO是什么sizeof(struct foo)返回时您可以定义通常的方式结构。你是那么基本上说,“富”是SIZE_OF_STRUCT_FOO字节的结构。然后,只要调用约定以同样的方式对待这两个结构中,它应该工作。

© www.soinside.com 2019 - 2024. All rights reserved.