GCC 4.4.3 смещение ошибки константного выражения. Как мне обойти это? - PullRequest
1 голос
/ 07 февраля 2012

У меня есть структура, которая содержит выражение статической константы, которое использует макрос смещения, определенный в stddef.h


struct SomeType {

    int m_member;
};

static const size_t memberOffset = offsetof(SomeType, m_member);

в GCC 4.4.3 (я использую Android NDK r7), это приводит к следующей ошибке:


arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi-v7a/... -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-exceptions -fno-rtti -O2 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 - -I/Users/Byron/bin/android-ndk-r7/sources/cxx-stl/system/include -
 -Wa,--noexecstack   -O0 -g -w -D_ANDROID   -I/blah/bin/android-ndk-r7/platforms/android-14/arch-arm/usr/include -c  
/MyFile.h:330: error: '->' cannot appear in a constant-expression
/MyFile.h:330: error: '&' cannot appear in a constant-expression

Это похоже на ошибку компилятора. У кого-нибудь есть хороший обходной путь для этого? Я нашел ссылки на такую ​​ошибку в GCC 3.4, но не в более поздних версиях. Ммм

Ответы [ 2 ]

2 голосов
/ 07 февраля 2012

Стандарты

В стандарте C ++ 98 есть некоторая информация в

C.2.4.1 Макрос offsetof ( тип , memberdesignator ) [diff.offsetof]

Макрос offsetof, определенный в <cstddef>, принимает ограниченный набор аргументов типа в этом международном стандарте.§18.1 описывает изменение.

(C.2.4.1 обнаружился с offsetof в содержании, поэтому я пошел туда первым.) И:

§18.1 Типы 18 Библиотека поддержки языков

¶5 Макрос offsetof принимает ограниченный набор аргументов типа в этом международном стандарте. type должен быть структурой POD или объединением POD (раздел 9).Результат применения макроса offsetof к полю, являющемуся статическим элементом данных или элементом функции, не определен.

Для сравнения, стандарт C99 гласит:

 offsetof(type, member-designator)

, который расширяется до целочисленного константного выражения, имеющего тип size_t, значение которого является смещением в байтах, до элемента структуры (обозначенного member-обозначение ) с начала его структуры(обозначается тип ). тип и обозначение элемента должно быть таким, чтобы при заданном

static type t;

выражение &(t.member-designator) преобразовывалось в адресную константу.(Если указанный член является битовым полем, поведение не определено.)


Ваш код

Ваш код соответствует требованиям стандартов C ++ и C,мне кажется.

Когда я использую G ++ 4.1.2 и GCC 4.5.1 в RedHat (RHEL 5), этот код без жалоб компилируется с параметрами -Wall -Wextra:

#include <cstddef>

struct SomeType {
    int m_member;
};

static const int memberOffset = offsetof(SomeType, m_member);

Он также без жалоб компилируется с #include <stddef.h> и с компиляторами GCC (если я использую struct SomeType в вызове макроса).

Интересно - я получал ошибки, пока не включил <cstddef> ... сделалВы включаете это?Конечно, я также добавил в объявление тип int.

Предполагая, что в вашем коде нет блокировок, мне кажется, что вы, вероятно, нашли ошибку в <cstddef>(или <stddef.h>) заголовок на вашей платформе.Вы не должны получать сообщение об ошибке, и G ++ на основе Linux подтверждает это.

Временные решения?

Вам нужно будет пересмотреть, как offsetof() определено в ваших системных заголовках.Затем вы, вероятно, переопределите его таким образом, чтобы не столкнуться с проблемой.

Возможно, вы сможете использовать что-то подобное, предполагая, что вы каким-то образом идентифицируете свою неисправную систему и выполняете #define BROKEN_OFFSETOF_MACRO (или добавляете -DBROKEN_OFFSETOF_MACRO в командную строку).

#include <cstddef>

#ifdef BROKEN_OFFSETOF_MACRO
#undef offsetof
#define offsetof(type, member)   ((size_t)((char *)&(*(type *)0).member - \
                                           (char *)&(*(type *)0)))
#endif /* BROKEN_OFFSETOF_MACRO */

struct SomeType {
    int m_member;
};

static const int memberOffset = offsetof(SomeType, m_member);

Приведение size_t присутствует, поскольку разница между двумя адресами составляет ptrdiff_t, а макрос offset() определен для возврата size_t.Макрос - не что иное, как уродливый, но именно поэтому он обычно скрыт в системном заголовке, где вам не нужно смотреть на него во всем его ужасном состоянии.Но когда все остальное терпит неудачу, вы должны делать все необходимое.

Я знаю, что однажды, примерно в 1990 году, я столкнулся с компилятором C, который не позволял бы 0, но вместо этого позволял бы 1024.Разданный заголовок <stddef.h>, конечно, использовал 0, поэтому я «исправил» его, изменив значение 0 на 1024 (дважды) на время (пока я не получил лучший компилятор на лучшей машине).

2 голосов
/ 07 февраля 2012

offsetof() должно быть определено с использованием арифметики указателя.GCC, вероятно, не нравится это в константных выражениях, потому что в теории указатели могут измениться, и поэтому это не const.Обходной путь мог бы сделать это static int без const?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...