头文件中的C typedef在文件范围内进行了可变修改

时间:2011-12-26 16:04:52

标签: c header typedef

我需要在两个源文件中包含一些typedef定义:

typedef double mat[MATSIZE][MATSIZE] ;

所以我创建了def.h,其中包括:

#ifndef DEF_H
#define DEF_H
typedef double mat[MATSIZE][MATSIZE] ;
#endif

并且在两个.c文件中我都包含它:

处理的第一个文件中的

#define MATSIZE 4
#include "def.h"

在第二个.c文件中:

extern int MATSIZE;
#include "def.h"

但是我得到了

error: variably modified ‘mat’ at file scope

我做错了什么?

3 个答案:

答案 0 :(得分:2)

可变长度数组(VGA)的概念对于C99来说是“新的”。

在C99之前,您只能使用实常数来指定数组的大小。以下代码在块范围或文件范围内都是非法的。

const int size = 42; /* size is not a real constant */
int boo[size];

C99为块范围引入了VLA 。上面的示例代码是合法的C99,只要它发生在块范围内。您的定义属于文件范围,因此无效。


同样的typedef引用两种不同的类型也是一个非常糟糕的想法。

答案 1 :(得分:2)

当在块外部(在文件范围或全局范围)定义数组时,必须在编译时知道该大小。这意味着数组上的每个维度必须是一个常量整数值(或者,对于第一个维度,它可以由数组的初始化程序隐含)。

如果您使用的是C89编译器,则可能会收到有关非常量数组维度的消息。 GCC 4.6.1给出了“在文件范围内可变修改mat的消息。

C99为曲目添加了可变长度数组,但它们只能出现在块或参数列表中,其中大小可以在运行时确定。

所以,在一个函数中,你可以合法地写:

extern int MATSIZE;

extern void func(void);

void func(void)
{
    typedef double mat[MATSIZE][MATSIZE];
    // ...
}

(需要函数声明来避免像:

这样的警告
warning: no previous prototype for ‘func’ [-Wmissing-prototypes]

因为我习惯用-Wmissing-prototypes编译。)

另一个问题是,在一个文件中,MATSIZE是编译时(#define d)常量;另一方面,显然存在整数变量MATSIZE。这些完全不相关。因此类型不同。


typdef是块范围

wildplasser关注typedef是否为块范围或全局。它是块作用域的,因为这个可执行的代码演示了:

#include <stdio.h>

static void function(void)
{
    typedef int i;
    i j = 1;
    printf("j = %d\n", j);
    {
    typedef double i;
    i j = 2.1;
    printf("j = %f\n", j);
    }
    {
    typedef char i[12];
    i j = "this works";
    printf("j = %s\n", j);
    }
}

int main(void)
{
    function();
    return(0);
}

如果我的代码审查存在,那将被立即拒绝。但是,它充分说明了一点。

答案 2 :(得分:1)

MATSIZE未知。这就是你遇到这个问题的原因。

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif