Why is the size of my class equal to zero? How can I guarantee that different objects have a different address?

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 are non-zero in 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; } 
+4
c ++ class
source share
4 answers

Defining your class is illegal. C ++ does not allow declaring an array with size 0 in any context. But even if you make your class definition empty, sizeof still needs to evaluate a nonzero value.

9/4 Completed objects and subobjects of a type class must have a nonzero size.

In other words, if your compiler takes a class definition and evaluates a value above sizeof to zero, this compiler goes beyond the standard C ++ language. This should be a compiler extension not related to standard C ++.

So, the only answer to the question is β€œwhy” in this case: because it is the way it is implemented in your compiler.

I don’t see that all this has to do with ensuring that different objects have different addresses. The compiler can easily enforce this, regardless of whether the size of the object is zero or not.

+8
source share

The standard says that having an array of size zero causes undefined behavior. When you run undefined behavior, other guarantees provided by the standard, for example, requiring the location of objects at a different address, may not be fulfilled.

Do not create arrays of zero size, and you should not have this problem.

+6
source share

This is pretty much a repetition of what other answers have already said, but a few more references to the ISO C ++ standard and some thoughts about the odd behavior of g ++.

The ISO C ++ 11 standard in section 8.3.4 [dcl.array], paragraph 1, states:

If there is a constant expression (5.19), it must be an integral constant expression and its value must be greater than zero.

Your class definition:

 class Test { int arr[0]; }; 

violates this rule. Section 1.4 [intro.compliance] is applicable here:

If the program contains a violation of any diagnosed rule [...], the corresponding implementation must issue at least one diagnostic message.

As I understand it, if the compiler issues this diagnostic and then accepts the program, the behavior of the program is undefined. So the whole standard has to say about your program.

Now this is a question about the compiler, not about the language.

I am using g ++ version 4.7.2, which allows arrays of zero size as an extension, but displays the required diagnostics (warning) if you call it, for example, -std=c++11 -pedantic :

 warning: ISO C++ forbids zero-size array 'arr' [-pedantic] 

(Apparently you are also using g ++.)

The experiment shows that g ++ handling zero-sized arrays is a bit odd. Here is an example based on one in your program:
 #include <iostream> class Empty { /* This is valid C++ */ }; class Almost_Empty { int arr[0]; }; int main() { Almost_Empty arr[2]; Almost_Empty x, y; std::cout << "sizeof (Empty) = " << sizeof (Empty) << "\n"; std::cout << "sizeof (Almost_Empty) = " << sizeof (Almost_Empty) << "\n"; std::cout << "sizeof arr[0] = " << sizeof arr[0] << '\n'; std::cout << "sizeof arr = " << sizeof arr << '\n'; if (&x == &y) { std::cout << "&x == &y\n"; } else { std::cout << "&x != &y\n"; } if (&arr[0] == &arr[1]) { std::cout << "&arr[0] == &arr[1]\n"; } else { std::cout << "&arr[0] != &arr[1]\n"; } } 

I received the required warning on int arr[0]; and then the following output:

 sizeof (Empty) = 1 sizeof (Almost_Empty) = 0 sizeof arr[0] = 0 sizeof arr = 0 &x != &y &arr[0] == &arr[1] 

C ++ requires that a class, even one without members, be at least 1 byte in size. g ++ follows this requirement for an Empty class that has no members. But adding a zero-size array to the class actually leads to the class having a size of 0.

If you declare two objects of type Almost_Empty , they have different addresses, which is reasonable; the compiler can select various objects as it sees fit.

But for elements in the array, the compiler has less flexibility: an array of N elements must have a size N times the number of elements.

In this case, since the Almost_Empty class has a size of 0, it follows that the array of Almost_Empty elements has a size of 0 * and that all elements of such an array have the same address.

This does not mean that g ++ does not comply with the C ++ standard. He did his job by printing out a diagnosis (even though it was not a deadly warning); after that, with regard to the standard, he can do whatever he likes.

But I would probably argue that this is a bug in g ++. From a common sense point of view, adding an empty array to a class should not reduce the class.

But there is a justification for this. As DyP points out in a comment, the gcc manual (which covers g ++) mentions this function as a C extension, which is also available for C ++ . They are primarily intended to be used as the last element of the structure, which is indeed the title for a variable-length object. This is called a struct hack . It is replaced on C99 with flexible array elements, and in C ++ with container classes.

My advice: avoid all this confusion without specifying arrays of zero length. If you really need sequences of elements that may be empty, use one of the standard C ++ container classes, for example std::vector or std::array .

+4
source share
  • There is a difference between variable declaration and variable initialization. In your case, you simply declare variables; A and B. After you have declared the variable, you need to initialize it with NEW or MALLOC.
  • Initialization now allocates memory to newly declared variables. You can initialize a variable with an arbitrary size or a block of memory.
  • A and B are variables, meaning you created two variables A and B. The compiler will identify this variable as unique variables, then it will allocate A to the memory address, say 2000, and then allocate B to another memory address, for example 150 .
  • If you want A to point to B or B to point to A, you can link to A or B, for example; A = & B. Now A as a reference to memory or address B, or rather, A points to B. This is called transmitting variables, in C ++ you can either pass variables by reference, or pass variables by value.
+1
source share

All Articles