Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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++.</p> <p>The ISO C++11 standard, in section 8.3.4 [dcl.array], paragraph 1, says:</p> <blockquote> <p>If the <em>constant-expression</em> (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.</p> </blockquote> <p>Your class definition:</p> <pre><code>class Test { int arr[0]; }; </code></pre> <p>violates this rule. Section 1.4 [intro.compliance] applies here:</p> <blockquote> <p>If a program contains a violation of any diagnosable rule [...], a conforming implementation shall issue at least one diagnostic message.</p> </blockquote> <p>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.</p> <p>Now it becomes a question about your compiler rather than about the language.</p> <p>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, <code>-std=c++11 -pedantic</code>:</p> <pre><code>warning: ISO C++ forbids zero-size array ‘arr’ [-pedantic] </code></pre> <p>(Apparently you're also using g++.)</p> <p>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:</p> <pre><code>#include &lt;iostream&gt; class Empty { /* This is valid C++ */ }; class Almost_Empty { int arr[0]; }; int main() { Almost_Empty arr[2]; Almost_Empty x, y; std::cout &lt;&lt; "sizeof (Empty) = " &lt;&lt; sizeof (Empty) &lt;&lt; "\n"; std::cout &lt;&lt; "sizeof (Almost_Empty) = " &lt;&lt; sizeof (Almost_Empty) &lt;&lt; "\n"; std::cout &lt;&lt; "sizeof arr[0] = " &lt;&lt; sizeof arr[0] &lt;&lt; '\n'; std::cout &lt;&lt; "sizeof arr = " &lt;&lt; sizeof arr &lt;&lt; '\n'; if (&amp;x == &amp;y) { std::cout &lt;&lt; "&amp;x == &amp;y\n"; } else { std::cout &lt;&lt; "&amp;x != &amp;y\n"; } if (&amp;arr[0] == &amp;arr[1]) { std::cout &lt;&lt; "&amp;arr[0] == &amp;arr[1]\n"; } else { std::cout &lt;&lt; "&amp;arr[0] != &amp;arr[1]\n"; } } </code></pre> <p>I get the required warning on <code>int arr[0];</code>, and then the following run-time output:</p> <pre><code>sizeof (Empty) = 1 sizeof (Almost_Empty) = 0 sizeof arr[0] = 0 sizeof arr = 0 &amp;x != &amp;y &amp;arr[0] == &amp;arr[1] </code></pre> <p>C++ requires a class, even one with no members, to have a size of at least 1 byte. g++ follows this requirement for class <code>Empty</code>, which has no members. But adding a zero-sized array to a class actually causes the class itself to have a size of 0.</p> <p>If you declare two objects of type <code>Almost_Empty</code>, they have distinct addresses, which is sensible; the compiler can allocate distinct objects any way it likes.</p> <p>But for elements in an array, a compiler has less flexibility: an array of N elements <em>must</em> have a size of N times the number of elements.</p> <p>In this case, since class <code>Almost_Empty</code> has a size of 0, it follows that an array of <code>Almost_Empty</code> elements has a size of 0 *and that all elements of such an array have the same address.</p> <p>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.</p> <p>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.</p> <p>But there is a rationale for it. As DyP points out in a comment, the gcc manual (which covers g++) <a href="http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html" rel="nofollow">mentions this feature</a> as a C extension which is <a href="http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html" rel="nofollow">also available for C++</a>. 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 <a href="http://c-faq.com/struct/structhack.html" rel="nofollow">struct hack</a>. It's replaced in C99 by flexible array members, and in C++ by container classes.</p> <p>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 <code>std::vector</code> or <code>std::array</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload