说,有一个proc.h定义了一个像
这样的数组proc.h:
struct proc
{
char p_stat;
char p_flags;
int p_pid;
} proc[100];
还有另外5个.c文件,包括此头文件。我没有看到任何这样的.c文件为这个数组分配内存。我认为它的链接器为它分配内存。但是,头文件中出现的内容应该只是一个声明。声明如何导致内存分配?我以为只有定义会导致内存分配。
谢谢,
答案 0 :(得分:3)
说,有一个proc.h定义了一个像
这样的数组proc.h:
struct proc { char p_stat; char p_flags; int p_pid; } proc[100];
上面的代码实际上不仅定义了数据结构struct proc
,还为包含标题的每个文件声明/分配了它们的数组。
一种广泛使用的习惯用于使用typedef定义数据结构,如下所示:
typedef struct
{
char p_stat;
char p_flags;
int p_pid;
} proc_t;
或只是简单的旧定义没有typedef的结构:
struct
{
char p_stat;
char p_flags;
int p_pid;
} proc_t;
然后在匹配标题的c文件中,您将实例化您的结构数组:
proc_t proc[100]; // if you've typedef'd the struct
struct proc_t proc[100]; // if you haven't typedef'd
然后在所有包含标题的c文件中,想要访问这个全局结构,你将声明变量extern。这样,所有的c文件都将共享对单个数据结构的访问权。
我更喜欢在单个头文件中键入一个结构,并通过函数调用(通过地址传递的对象)访问/操作该数据结构的实例来封装它,但这是个人品味和whatevs的问题。
答案 1 :(得分:2)
include
指令只是将包含的文件插入包含它的文件中。换句话说,所有.c
文件分别声明结构,并为变量proc
声明(分配内存)。它们都为单独定义内存。如果所有这些都后来编译在一起,我不知道这怎么可能正常工作。
答案 2 :(得分:2)
我没有看到任何这样的.c文件为这个数组分配内存。
实际上,他们都这样做:声明和定义被逐字复制到包含标题的每个翻译单元中,因此每个翻译单元都有自己对proc[100]
数组的定义。
如果您尝试将翻译结果链接在一起,您应该看到链接器产生的重新定义错误,除非实际的标头声明proc
静态。
当然,创建proc[100]
的正确方法是在标头中声明extern
,并在其中一个.c
文件中提供定义。
答案 3 :(得分:2)
'头'文件是包含(成为C文件的一部分)。您已在头文件中声明并定义了数组,然后将该声明包含在您的五个C文件中,因此空间被分配了5次。你想要做的是在头文件中使proc
数组成为extern
声明,然后在你的一个C文件中复制完全相同的声明(不带extern
)。
或者,你可以用宏完成同样的事情,如下:
// foo.h
#ifndef MAIN
/*
* this declaration is extern for everybody except the
* MAIN module, (typically main.c) which defines
* the macro MAIN -- this ensures that all C files see the same
* structure definition, but space is allocated exactly once.
*/
extern struct proc {
#else
struct proc {
#endif
…
} proc[100];
在你的一个C文件中(例如main),你可以这样做:
// main.c
#define MAIN
// when you include foo.h, the 'extern' will be left out, and space will be allocated
#include "foo.h"
在您的其他C文件中,您只需执行此操作:
// other.c
#include "foo.h"
这将导致数组的空间被分配一次(在main.o中),而其他.o文件将包含对proc []的外部引用,这将由链接器解析。
答案 4 :(得分:1)
正如Morten Jensen所说,这与做:
相同typdef struct proc
{
// ...
} proc_t;
proc_t proc[100];
这是proc的定义(不仅仅是声明)。然而,这可能是一个错误。如果此标头包含在多个翻译单元中,则是未定义的行为。
(我发布这个答案是因为到目前为止所有其他答案都说它创建了proc
的多个副本,但这是错误的!)
对于外部可见变量的两个(或更多)定义,它是未定义的行为。
如果意图是从多个单位看到一个变量,那么proc_t proc[100];
需要用声明替换:
extern proc_t proc[100];
然后只有一个单位执行定义proc_t proc[100]
。
如果意图是所有单位都有proc
的单独副本,则替换为此定义:
static proc_t proc[100];
在这两种情况下,proc
都具有所谓的静态存储持续时间。这意味着在程序启动期间分配内存。