简体   繁体   中英

C typedef in header file variably modified at file scope

I need to include some typedef definition in two source files:

typedef double mat[MATSIZE][MATSIZE] ;

so I created def.h which includes:

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

and in both .c files I included it by:

in the first file processed:

#define MATSIZE 4
#include "def.h"

in the second .c file:

extern int MATSIZE;
#include "def.h"

But I get

error: variably modified ‘mat’ at file scope

What did I do wrong?

The concept of Variable Length Arrays (VLAs) is "new" to C99.

Before C99 you could only use real constants for specifying sizes of arrays. The following code was illegal either in block scope or file scope.

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

C99 introduced VLA for block scope . The example code above is legal C99, provided it happens in block scope. Your definition is at file scope and therefore invalid.


Also it is a really bad bad idea to have the same typedef refer to two different types.

When arrays are defined outside a block (at file scope or global scope), the size must be known at compile time. That means that the each dimension on the array must be a constant integral value (or, for the first dimension, it could be implied by the initializer for the array).

If you used a C89 compiler, you might get a message about non-constant array dimensions. GCC 4.6.1 gives the 'variably modified mat at file scope' message.

C99 added Variable Length Arrays to the repertoire, but they can only appear inside a block or an argument list, where the size can be determined at runtime.

So, in a function, you could legitimately write:

extern int MATSIZE;

extern void func(void);

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

(The function declaration is needed to avoid the warnings like:

warning: no previous prototype for ‘func’ [-Wmissing-prototypes]

since I habitually compile with -Wmissing-prototypes .)

The other issue is that in one file, MATSIZE is a compile-time ( #define d) constant; in the other, there is apparently an integer variable MATSIZE . These are completely unrelated. The types therefore are different.


typdef is block scoped

wildplasser is concerned about whether typedef is block-scoped or global. It is block-scoped, as this otherwise execrable code demonstrates:

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

If that was present to me for code review, it would be summarily rejected. However, it amply demonstrates a point.

MATSIZE is not known. Which is why you are getting this issue.

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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