我需要在两个源文件中包含一些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
我做错了什么?
答案 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
。这些完全不相关。因此类型不同。
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