如何在头文件中定义(声明?)数组的内存?

时间:2014-07-10 16:26:04

标签: c

说,有一个proc.h定义了一个像

这样的数组

proc.h:

struct proc
{
 char p_stat;
 char p_flags;
 int p_pid;
} proc[100];

还有另外5个.c文件,包括此头文件。我没有看到任何这样的.c文件为这个数组分配内存。我认为它的链接器为它分配内存。但是,头文件中出现的内容应该只是一个声明。声明如何导致内存分配?我以为只有定义会导致内存分配。

谢谢,

5 个答案:

答案 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都具有所谓的静态存储持续时间。这意味着在程序启动期间分配内存。