GCC 4.4.3常量表达式错误的偏移.我应该如何解决这个问题
GCC 4.4.3 offsetof constant expression bug. How should I work around this?
我有一个结构,它包含一个静态常量表达式,该表达式使用stddef.h 中定义的偏移量宏
struct SomeType {
int m_member;
};
static const size_t memberOffset = offsetof(SomeType, m_member);
在GCC 4.4.3中(我使用的是Androids 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上找到了这种性质的bug的参考,但没有更新的版本。hmmm
标准
在C++98标准中,中有一些信息
C.2.4.1宏
offsetof
(类型,成员指示符)[diff.offsetof]在
<cstddef>
中定义的宏offsetof
接受此International标准§18.1描述了该变更。
(C.2.4.1在内容中显示offsetof
,所以我先去了那里。)和:
§18.1类型18语言支持库
¶5宏
offsetof
接受本国际标准中的一组受限类型自变量类型应为POD结构或POD联合(第9条)。将offsetof宏应用于字段的结果是静态数据成员,或者函数成员未定义。
为了进行比较,C99标准规定:
offsetof(type, member-designator)
其扩展为具有类型
size_t
的整数常量表达式其是以字节为单位的偏移量)到结构成员(由成员指示符指定),从其结构的开始(由类型指定)。类型和成员指示符应使得给定static type t;
则表达式CCD_ 7评估为地址常数。(如果指定的成员是位字段,行为未定义。)
您的代码
在我看来,您的代码符合C++和C标准的要求。
当我在RedHat(RHEL 5)上使用G++4.1.2和GCC 4.5.1时,此代码的编译不会受到-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>
)标头中发现了一个错误。您不应该得到错误,而基于Linux的G++似乎证实了这一点。
解决方法
您需要查看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);
由于两个地址之间的差为ptrdiff_t
,并且offset()
宏被定义为返回size_t
,因此存在size_t
强制转换。这个宏很难看,但这就是为什么它通常隐藏在系统头中,你不必看它的所有可怕之处。但是,当其他一切都失败时,你必须做任何必要的事情。
我知道有一次,大约在1990年,我遇到了一个C编译器,它不允许0,但允许1024。当然,分布式<stddef.h>
标头使用了0
,所以我通过在持续时间内将0更改为1024(两次)来"修复"它(直到我在更好的机器上获得更好的编译器)。
offsetof()
必须使用指针算术进行定义。GCC可能不喜欢常量表达式中的这种情况,因为理论上指针可能会改变,所以它是非const
。变通办法可能是让它成为没有const
的static int
?
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- Ardunio UNO解决了多个重叠的定时器循环
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 两个文件使用彼此的功能-如何解决
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 如何解决"invalid conversion from 'char' to 'const char*'"
- 在java中解决这段代码时面临循环中的问题
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 难以理解某些人解决IOI问题的源代码
- visual c++,如何获取解决方案目录中的代码
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- 节俭并发:未解决的外部问题
- IpOpt拒绝解决不受约束的问题
- 如何解决这个超硬恒星的创造问题
- 循环无限运行C++解决骑士之旅问题
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- 为什么这段代码不起作用,我该如何解决?