繁体   English   中英

头文件中的C typedef在文件范围内可变地修改

[英]C typedef in header file variably modified at file scope

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

我做错了什么?

可变长度数组(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 ”消息。

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);
}

如果提供给我进行代码审查,则该摘要将被拒绝。 但是,它充分说明了这一点。

MATSIZE未知。 这就是为什么您遇到此问题。

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM