I created a class but its size is zero. Now, how can I be sure that all objects have different addresses? (As we know, empty classes have a non-zero size.)
#include<cstdio>
#include<iostream>
using namespace std;
class Test
{
int arr[0];//Why is the sizezero?
};
int main()
{
Test a,b;
cout <<"size of class"<<sizeof(a)<<endl;
if (&a == &b)// now how we ensure about address of objects ?
cout << "impossible " << endl;
else
cout << "Fine " << endl;//Why isn't the address the same?
return 0;
}
This is largely a repetition of what the other answers have already said, but with a few more references to the ISO C++ standard and some musings about the odd behavior of g++.
The ISO C++11 standard, in section 8.3.4 [dcl.array], paragraph 1, says:
Your class definition:
violates this rule. Section 1.4 [intro.compliance] applies here:
As I understand it, if a compiler issues this diagnostic and then accepts the program, the program's behavior is undefined. So that's all the standard has to say about your program.
Now it becomes a question about your compiler rather than about the language.
I'm using g++ version 4.7.2, which does permit zero-sized arrays as an extension, but prints the required diagnostic (a warning) if you invoke it with, for example,
-std=c++11 -pedantic
:(Apparently you're also using g++.)
Experiment shows that g++'s treatment of zero-sized arrays is a bit odd. Here's an example, based on the one in your program:
I get the required warning on
int arr[0];
, and then the following run-time output:C++ requires a class, even one with no members, to have a size of at least 1 byte. g++ follows this requirement for class
Empty
, which has no members. But adding a zero-sized array to a class actually causes the class itself to have a size of 0.If you declare two objects of type
Almost_Empty
, they have distinct addresses, which is sensible; the compiler can allocate distinct objects any way it likes.But for elements in an array, a compiler has less flexibility: an array of N elements must have a size of N times the number of elements.
In this case, since class
Almost_Empty
has a size of 0, it follows that an array ofAlmost_Empty
elements has a size of 0 *and that all elements of such an array have the same address.This does not indicate that g++ fails to conform to the C++ standard. It's done its job by printing a diagnostic (even though it's a non-fatal warning); after that, as far as the standard is concerned, it's free to do whatever it likes.
But I would probably argue that it's a bug in g++. Just in terms of common sense, adding an empty array to a class should not make the class smaller.
But there is a rationale for it. As DyP points out in a comment, the gcc manual (which covers g++) mentions this feature as a C extension which is also available for C++. They are intended primarily to be used as the last member of a structure that's really a header for a variable-length object. This is known as the struct hack. It's replaced in C99 by flexible array members, and in C++ by container classes.
My advice: Avoid all this confusion by not defining zero-length arrays. If you really need sequences of elements that can be empty, use one of the C++ standard container classes such as
std::vector
orstd::array
.The standard says that having an array of zero size causes undefined behavior. When you trigger undefined behavior, other guarantees that the standard provides, such as requiring that objects be located at a different address, may not hold.
Don't create arrays of zero size, and you shouldn't have this problem.
Your class definition is illegal. C++ does not allow array declarations with size
0
in any context. But even if you make your class definition completely empty, thesizeof
is still required to evaluate to a non-zero value.In other words, if your compiler accepts the class definition and evaluates the above
sizeof
to zero, that compiler is going outside of scope of standard C++ language. It must be a compiler extension that has no relation to standard C++.So, the only answer to the "why" question in this case is: because that's the way it is implemented in your compiler.
I don't see what it all has to do with ensuring that different objects have different addresses. The compiler can easily enforce this regardless of whether object size is zero or not.