C typedef в заголовочном файле, изменяемый в объеме файла - PullRequest
1 голос
/ 26 декабря 2011

Мне нужно включить определение 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 ]

2 голосов
/ 26 декабря 2011

Концепция массивов переменной длины (VLA) является "новой" для C99.

До C99 вы могли использовать только реальные константы для указания размеров массивов. Следующий код был недопустим в области блока или файла.

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

C99 представил VLA для области действия блока . Приведенный выше пример кода является допустимым C99, если это происходит в области блока. Ваше определение находится в области видимости файла и поэтому недействительно.


Также очень очень плохо идея иметь одинаковые typedef для двух разных типов.

2 голосов
/ 26 декабря 2011

Когда массивы определены вне блока (в области файла или в глобальной области), размер должен быть известен во время компиляции. Это означает, что каждое измерение в массиве должно быть постоянным интегральным значением (или, для первого измерения, оно может подразумеваться инициализатором для массива).

Если вы использовали компилятор 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);
}

Если бы он был представлен мне для проверки кода, он был бы отклонен. Тем не менее, это наглядно демонстрирует точку.

1 голос
/ 26 декабря 2011

MATSIZE не известен. Вот почему вы получаете эту проблему.

#ifndef DEF_H
#define DEF_H

#define MATSIZE 100 /* or whatever */

typedef double mat[MATSIZE][MATSIZE]

#endif 
...