简体   繁体   English

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

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

We all know that sizeof an empty class or an object of empty class will be 1 byte. 我们都知道空类的大小或空类的对象将是1个字节。 I came across something where sizeof a class and its object is coming as 0. The program is syntactically correct as there were no compilation or run time errors. 我遇到了一个类的sizeof及其对象变为0的东西。该程序在语法上是正确的,因为没有编译或运行时错误。 Is this undefined behavior? 这是未定义的行为吗? The use case I'm trying to execute makes any sense and looks like a valid one? 我试图执行的用例有意义,看起来像一个有效的用例? Is it a big blunder to not to give exact subscript or size for an array in the class? 不给类中的数组提供精确的下标或大小是一个很大的错误吗? The code snippet is as below: 代码段如下:

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

output: 输出:

0 0

0 0

The sizeof an empty class is one byte (non zero basically) and the reason for that is said like "To make sure that different objects have different addresses". 空类的sizeof是一个字节(基本上不为零),其原因类似于“确保不同的对象具有不同的地址”。

What happens in this case then when sizeof class is coming a zero? 在这种情况下,当sizeof类变为零时会发生什么? Note: Observed the same behavior for int a[] as well. 注意:也观察到int a[]的相同行为。

It's called "flexible array member" and it's a feature of C99 (I think). 它被称为“灵活的阵列成员” ,它是C99的一个特征(我认为)。 It's not valid C++ - you don't have warnings/errors, probably because the compiler supports it as an extension. 它不是有效的C ++ - 你没有警告/错误,可能是因为编译器支持它作为扩展。

Compiling with -Wall -Wextra -pedantic -std=c++NN (98, 03, 11, 14, ..) should generate warning (the last two flags will disable any compiler extensions). -Wall -Wextra -pedantic -std=c++NN-Wall -Wextra -pedantic -std=c++NN ,..)应该生成警告(最后两个标志将禁用任何编译器扩展)。


You can see some information in this related question: Is using flexible array members in C bad practice? 您可以在此相关问题中看到一些信息: 在C练习中使用灵活的数组成员吗?

For example, here's what GCC says about this: 例如,以下是GCC对此的说法:

In ISO C99, you would use a flexible array member, which is slightly different in syntax and semantics: 在ISO C99中,您将使用灵活的数组成员,它在语法和语义上略有不同:
... ...
Flexible array members have incomplete type, and so the sizeof operator may not be applied. 灵活的数组成员具有不完整的类型,因此可能不会应用sizeof运算符。 As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero . 作为零长度数组的原始实现的怪癖,sizeof的计算结果为零

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

This explains the 0 size of char a[] and not the 0 for the class, but as I already mentioned - it's a C feature and not a valid C++. 这解释了char a[]0大小而不是类的0,但正如我已经提到的 - 它是C特性而不是有效的C ++。

If you compile with -pedantic flag 如果使用-pedantic标志进行编译

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

C++ does not support VLA s and thus your class declaration is not legal and going outside the scope of standard C++ rules. C ++不支持VLA ,因此您的类声明不合法,超出了标准C ++规则的范围。

Your code is not standard C++, thus I can not see any sense in that. 你的代码不是标准的C ++,因此我看不出任何意义。

If you use pedantic flag, you should receive this: 如果你使用迂腐旗,你应该收到:

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

Try changing your class to 尝试将班级改为

class A {
   char a[5];
};

then you should get an output of 那么你应该得到一个输出

5
5

like you should expect. 就像你应该期待的那样

However, you can argue that without the flag, your code does compile and outputs zeroes. 但是,您可以争辩说,如果没有标志,您的代码会编译并输出零。 As a counter I could say that the same goes if you use this class: 作为一个计数器,我可以说如果你使用这个类也一样:

class A {
   char a[0];
};

but I am pretty sure you know that zero-sized arrays are not allowed, but still this thing compiles fine and gives an output of zeroes. 但我很确定你知道不允许使用零大小的数组,但是这个东西编译得很好并且输出为0。

Empty base classes can be optimized to zero bytes, which would technically make sizeof(base) also 0 . 空基类可以优化为零字节,这在技术上会使sizeof(base)也为0

The "1 byte" thing is really an implementation detail, coming from the rule that distinct objects need to have distinct addresses. “1字节”的东西实际上是一个实现细节,来自不同对象需要具有不同地址的规则。

So: 所以:

struct base { };

struct derived : base { };

Both sizeof(base) and sizeof(derived) are allowed to be 0 , because the derived object is the same object as the base object contained within. sizeof(base)sizeof(derived)都允许为0 ,因为derived对象与包含在其中的base对象是同一个对象。

However: 然而:

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

Here, sizeof(derived) must be 1, because the standard requires that 这里, sizeof(derived)必须为1,因为标准要求

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

Similarly: 同理:

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

requires that 要求

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

Many compiler vendors take the shortcut and simply make empty classes take up one byte. 许多编译器供应商采用快捷方式,只需使空类占用一个字节。

The size of a class can be 0. Consider the following piece of code 类的大小可以是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

So, accessing functions present in the class with a size 0 leads to compilation error. 因此,访问类中存在的大小为0的函数会导致编译错误。

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

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