这个gcc是不是太好了,做了开发人员认为它会做的事情,或者是对某些事情过于挑剔的铿锵声。我是否在标准中遗漏了一些微妙的规则,其中clang实际上正在抱怨这个
或者我应该使用第二位代码,这基本上就是偏移量的工作原理
[adrian@localhost ~]$ g++ -Wall -pedantic -ansi a.cc
[adrian@localhost ~]$ a.out
50
[adrian@localhost ~]$ cat a.cc
#include <iostream>
struct Foo
{
char name[50];
};
int main(int argc, char *argv[])
{
std::cout << sizeof(Foo::name) << std::endl;
return 0;
}
[adrian@localhost ~]$ clang++ a.cc
a.cc:10:29: error: invalid use of non-static data member 'name'
std::cout << sizeof(Foo::name) << std::endl;
~~~~~^~~~
1 error generated.
[adrian@localhost ~]$ g++ -Wall -pedantic -ansi b.cc
[adrian@localhost ~]$ a.out
50
[adrian@localhost ~]$ cat b.cc
#include <iostream>
struct Foo
{
char name[50];
};
int main(int argc, char *argv[])
{
std::cout << sizeof(static_cast<Foo*>(0)->name) << std::endl;
return 0;
}
[adrian@localhost ~]$ clang++ b.cc
[adrian@localhost ~]$ a.out
50
答案 0 :(得分:1)
我发现添加
-std=c++11
会阻止它抱怨。 GCC很好 在任一版本中使用它。
现代GCC版本即使在-std=c++98
模式下也允许这样做。但是,旧的版本,如我的GCC 3.3.6,做抱怨并拒绝编译。
所以现在我想知道C ++ 98的哪一部分违反了这段代码。
维基百科明确指出这样的功能是在C ++ 11中添加的,并且引用了N2253,它表示C ++ 98标准最初认为语法无效,但后来有意澄清为不允许这样做(我不知道非静态成员字段与其数据类型的其他变量有何不同)。一段时间后,他们决定使这种语法有效,但直到C ++ 11。
同一份文件提到了一个丑陋的解决方法,也可以在整个网络上看到:
sizeof(((Class*) 0)->Field)
看起来简单地使用0
,NULL
或nullptr
可能会触发编译器警告,以便可能取消引用空指针(尽管sizeof
永远不会评估其参数),因此可能会使用任意的非零值,尽管它看起来像一个反直觉的“魔法常数”。因此,在我的C ++优雅降级层中,我使用:
#if __cplusplus >= 201103L
#define CXX_MODERN 2011
#else
#define CXX_LEGACY 1998
#endif
#ifdef CXX_MODERN
#define CXX_FEATURE_SIZEOF_NONSTATIC
#define CxxSizeOf(TYPE, FIELD) (sizeof TYPE::FIELD)
#else
// Use of `nullptr` may trigger warnings.
#define CxxSizeOf(TYPE, FIELD) (sizeof (reinterpret_cast<const TYPE*>(1234)->FIELD))
#endif
用法示例:
// On block level:
class SomeHeader {
public:
uint16_t Flags;
static CxxConstExpr size_t FixedSize =
#ifdef CXX_FEATURE_SIZEOF_NONSTATIC
(sizeof Flags)
#else
sizeof(uint16_t)
#endif
;
}; // end class SomeHeader
// Inside a function:
void Foo(void) {
size_t nSize = CxxSizeOf(SomeHeader, Flags);
} // end function Foo(void)
顺便说一句,请注意sizeof(Type)
和sizeof Expression
的语法差异,因为它们在形式上并不相同,即使sizeof(Expression)
有效 - 只要sizeof (Expression)
是sizeof(decltype(Expression))
有效。因此,最正确和可移植的形式是typeof(Expression)
,但遗憾的是它仅在C ++ 11中可用;一些编制者长期提供data.table
,但这绝不是标准的扩展。