2015-05-05 5 views
3

При компиляции под кодом, использующим GCC 4.8.3, появляется сообщение об ошибке «arrTest.c: 12: 4: ошибка: объект с переменным размером не может быть инициализирован». Но тот же код компилируется отлично при компиляции с GCC 4.1. Может ли кто-нибудь помочь мне исправить это?ошибка компиляции при смещении элемента структуры, используемого как длина массива

#define OFFSET(structure, member) /* byte offset of member in structure*/\ 
       ((const int) &(((structure *) 0) -> member)) 

typedef struct test{ 
    int a; 
    char b; 
    int c; 
}test; 

void main() 
{ 
    int arr[OFFSET(test, b)] = {0}; 

    printf("%d %d\n", arr[0], OFFSET(test, b)); 

    return; 
} 

Хотя удаление инициализации массива устранит проблему. Но в моем коде есть много таких примеров. Поэтому я не хочу идти куда угодно и изменять. Я хотел знать, существует ли какой-либо путь в GCC 4.8, чтобы исправить это либо с помощью некоторых флагов компиляции, либо с изменением определения MACRO, поскольку тот же код скомпилирован с GCC 4.1.

+0

изменить 'int arr [OFFSET (test, b)] = {0};' to 'int arr [OFFSET (test, b)];' –

+0

Спасибо, Grijesh, на самом деле в моем коде много таких примеров , Поэтому я не хочу идти куда угодно и изменять, как вы предложили. Я хотел знать, существует ли какой-либо путь в GCC 4.8, чтобы исправить это либо с помощью некоторых флагов компиляции, либо с изменением определения MACRO, поскольку тот же код скомпилирован с GCC 4.1. –

+0

Я считаю, что должно быть что-то. Вы также должны добавить эту информацию в комментарии к вопросу внизу. –

ответ

3

Ваш OFFSET макрос неверен в современном языке C как разыменование нулевого указателя - это неопределенное поведение; кроме того, в современном C нет положения для произвольной арифметики указателя, чтобы привести к постоянной времени компиляции, поэтому gcc жалуется на то, что массив имеет переменный размер.

К счастью, современная С поставляет offsetof macro in stddef.h, который полностью определенное поведение и результаты в постоянная время компиляции:

#include <stddef.h> 
#define OFFSET(structure,member) offsetof(structure, member) 

// rest of code 

Live example.

У меня нет доступа к старому, как компилятор, как GCC 4.1, но если это происходит не поддерживать offsetof, то вы можете упасть обратно к определению с помощью препроцессора условной проверки версии:

#ifdef __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC__MINOR__ >= 8)) 
# include <stddef.h> 
# define OFFSET(structure,member) offsetof(structure, member) 
#else 
# define OFFSET(structure, member) /* byte offset of member in structure*/\ 
      ((const int) &(((structure *) 0) -> member)) 
#endif 
+0

Я бы предположил, что 'OFFSET' (несмотря на внешний вид) не является константой времени компиляции, так что' arr' будет массивом переменной длины в коде OP. 'offsetof', напротив, является константой целочисленного времени компиляции, приводящей к определению« нормального »массива. –

+0

@PeterSchneider спасибо, я расширил ответ. – ecatmur

+0

Спасибо, он работает. –

2

Try C библиотеки offsetof() макрос. В GCC используется функция __builtin_offset() и, похоже, работает нормально.

Смежные вопросы