繁体   English   中英

一个类或对象的“sizeof”可以为零吗?

[英]Can “sizeof” a class or object ever be zero?

我们都知道空类的大小或空类的对象将是1个字节。 我遇到了一个类的sizeof及其对象变为0的东西。该程序在语法上是正确的,因为没有编译或运行时错误。 这是未定义的行为吗? 我试图执行的用例有意义,看起来像一个有效的用例? 不给类中的数组提供精确的下标或大小是一个很大的错误吗? 代码段如下:

#include<iostream>
using namespace std;
class A
{
   char a[];
};
int main()
{
    A b;
    cout<<sizeof(A)<<endl;
    cout<<sizeof(b)<<endl;
    return 0;
}

输出:

0

0

空类的sizeof是一个字节(基本上不为零),其原因类似于“确保不同的对象具有不同的地址”。

在这种情况下,当sizeof类变为零时会发生什么? 注意:也观察到int a[]的相同行为。

它被称为“灵活的阵列成员” ,它是C99的一个特征(我认为)。 它不是有效的C ++ - 你没有警告/错误,可能是因为编译器支持它作为扩展。

-Wall -Wextra -pedantic -std=c++NN-Wall -Wextra -pedantic -std=c++NN ,..)应该生成警告(最后两个标志将禁用任何编译器扩展)。


您可以在此相关问题中看到一些信息: 在C练习中使用灵活的数组成员吗?

例如,以下是GCC对此的说法:

在ISO C99中,您将使用灵活的数组成员,它在语法和语义上略有不同:
...
灵活的数组成员具有不完整的类型,因此可能不会应用sizeof运算符。 作为零长度数组的原始实现的怪癖,sizeof的计算结果为零

(来源: https//gcc.gnu.org/onlinedocs/gcc/Zero-Length.html )。

这解释了char a[]0大小而不是类的0,但正如我已经提到的 - 它是C特性而不是有效的C ++。

如果使用-pedantic标志进行编译

$ g ++ -W -Wall -pedantic prog.cpp
prog.cpp:5:11:警告:ISO C ++禁止零大小数组'a'[-pedantic]

C ++不支持VLA ,因此您的类声明不合法,超出了标准C ++规则的范围。

你的代码不是标准的C ++,因此我看不出任何意义。

如果你使用迂腐旗,你应该收到:

gsamaras@pythagoras:~$ g++ -pedantic file.cpp
file.cpp:5:11: warning: ISO C++ forbids zero-size array ‘a’ [-Wpedantic]
    char a[];
         ^

尝试将班级改为

class A {
   char a[5];
};

那么你应该得到一个输出

5
5

就像你应该期待的那样

但是,您可以争辩说,如果没有标志,您的代码会编译并输出零。 作为一个计数器,我可以说如果你使用这个类也一样:

class A {
   char a[0];
};

但我很确定你知道不允许使用零大小的数组,但是这个东西编译得很好并且输出为0。

空基类可以优化为零字节,这在技术上会使sizeof(base)也为0

“1字节”的东西实际上是一个实现细节,来自不同对象需要具有不同地址的规则。

所以:

struct base { };

struct derived : base { };

sizeof(base)sizeof(derived)都允许为0 ,因为derived对象与包含在其中的base对象是同一个对象。

然而:

struct base1 { };
struct base2 { };
struct derived : base1, base2 { };

这里, sizeof(derived)必须为1,因为标准要求

derived d;
assert(static_cast<base1 *>(&d) != static_cast<base2 *>(&d));

同理:

struct type1 { };
struct type2 { };
struct combined { type1 obj1; type2 obj2; };

要求

combined c;
assert(&c.obj1 != &c.obj2);

许多编译器供应商采用快捷方式,只需使空类占用一个字节。

类的大小可以是0.考虑下面的代码

#include <iostream>
using namespace std;

class A
{
    public:
    int a[0];
    void getA(){
        cout<<"Hello World";
    }
};

class B
{
};

int main()
{
    cout<<"The size of A is "<<sizeof(A)<<endl;   // prints 0
    A w;
    cout<<"The size of object of A is "<<sizeof(w)<<endl;    //prints 0
    cout<<"The size of the array a in A is "<<sizeof(w.a)<<endl;  // prints 0
    cout<<"The value from function of class A is  "<<w.getA()<<endl;  // Gives a compilation error
    cout<<"The size of B is "<<sizeof(B)<<endl;  //prints 1
}


Output:
The size of A is 0
The size of object of A is 0
The size of the array a in A is 0
The size of B is 1

因此,访问类中存在的大小为0的函数会导致编译错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM