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

头文件中的C typedef在文件范围内进行了可变修改,c,header,typedef,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

我需要在两个源文件中包含一些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

我做错了什么?

不知道MATSIZE。这就是为什么你会遇到这个问题

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif 

MATSIZE不得而知。这就是为什么你会遇到这个问题

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif 

可变长度阵列(VLA)的概念对C99来说是“新的”

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

const int size = 42; /* size is not a real constant */
int boo[size];
C99为块范围引入了VLA。上面的示例代码是合法的C99,前提是它发生在块范围内。您的定义在文件范围内,因此无效



另外,让同一类型的def表示两种不同的类型是一个非常糟糕的想法。

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

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

const int size = 42; /* size is not a real constant */
int boo[size];
C99为块范围引入了VLA。上面的示例代码是合法的C99,前提是它发生在块范围内。您的定义在文件范围内,因此无效



另外,让同一个typedef引用两种不同的类型是一个非常糟糕的想法。

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

如果使用C89编译器,可能会收到一条关于非常量数组维度的消息。GCC 4.6.1给出了“文件范围内的可变修改
mat
at file scope”消息

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原型编译

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


typdef是块范围的 关注
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);
}
#包括
静态空隙函数(void)
{
类型定义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=“这是有效的”;
printf(“j=%s\n”,j);
}
}
内部主(空)
{
函数();
返回(0);
}

如果提交给我进行代码审查,它将被立即拒绝。但是,它充分说明了一点。

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

如果使用C89编译器,可能会收到一条关于非常量数组维度的消息。GCC 4.6.1给出了“文件范围内的可变修改
mat
at file scope”消息

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原型编译

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


typdef是块范围的 关注
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);
}
#包括
静态空隙函数(void)
{
类型定义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=“这是有效的”;
printf(“j=%s\n”,j);
}
}
内部主(空)
{
函数();
返回(0);
}

如果提交给我进行代码审查,它将被立即拒绝。但是,它充分说明了一点。

您还必须定义
MATSIZE
。请看,我有“#define MATSIZE 4#define MATLENGTH MATSIZE*MATSIZE”#在其中一个先处理的.c文件中包含“def.h”和“extern int MATSIZE#在secondOne.c文件中包含“def.h”表示MATSIZE是一个常量。另一个说这是一个(外部)int。其中一个在撒谎……不。在文件1中,它是一个预处理器定义。每次出现字符串“4”时,它都会指示预处理器将字符串“MATSIZE”替换为字符串“4”。(因此编译器在扫描.h文件时将有效地看到
typedef double mat[4][4];
)。第二个.c文件声明了一个名为MATSIZE(但值未知)的(外部)int,因此编译器将有效地看到
typedef double-mat[MATSIZE][MATZIZE]扫描.h文件时,认为MATSIZE是一个具有未知值的(外部)int;这是不可接受的。是的,或多或少。您想要的是,保证“mat”的typedef每次被anot包含时都会生成完全相同的类型