Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Declaring zero sized array say
int x[0];
directly in function gives compiler error.
We are not allowed to create an array of zero size.

But when we create a structure have this zero size array then why it is allowed?
C++
struct xyz
{
    int x;
    char y;
    int z[0];
};
struct xyz C;

Why does sizeof(C) returns 8 bytes?
What might be the purpose of inserting such zero sized array in structure?
Posted

It is a placeholder - it means that the struct will not have the same size every time it is returned.
Basically, think about a structure that returns information, based on the value you as for: if you ask for Ids for all machines on the network, it returns an array of Ids. If you ask for a specific machine id, the array is unused.
It's a hangover from C, and frankly there are better ways to do this in C++
 
Share this answer
 
Comments
Malli_S 21-Dec-11 3:54am    
But that can be achieved from union, what's specialty having structure with zero sized array ?
rupeshkp728 21-Dec-11 5:18am    
Thanks Griff.
That's a practice inherited from C. But your first question is unrelated.

Why 8 bytes


The day where memory was physically organized in bytes has gone with the 8bit microprocessors. Processor with larger "words" don't move bytes as their native unit. Accessing individual bytes, in fact, requires to the processor a masking and a shift. To avid this "penality" individual struct fields are "aligned" on a "processor word boundary". For 32 bit processor this is 4 bytes.
Your struct is 8 bytes long because 4 serves the int x, and other 4 serves char y (1 is the char, the other 3 are padding).

What's the zero size


C is not "strongly typed" as C++ is, and has no "support for dynamic structures".
The zero sized array is essentially a way to allow expression like
C.z[3]

allowing you to access the 4rd (3+1) int after the struct beginning address.
In your case (where C is on-stack) this will write something else (causing undefined behavior)

But with dynamic memory, the idea is something like
// get enough raw memory
xyz* ptr = (xyx*)malloc(sizeof(xyz)+4*sieof(int));
// in-pace construct the C++ variables (not really needed here, being xyz a POD
new(ptr) xyz;
new(&ptr->z)int[4];
// do something with the variables
ptr->x = 1;
ptr->y = 'a';
ptr->z[0] = 10;
ptr->z[1] = 11;
ptr->z[2] = 12;
ptr->z[3] = 13; //< no more than this, otherwise will go out of memory
/*
 * your useful stuff goes here
 */
// explicitly destroy C++ objects (not really needed being xyz a POD)
for(i=0;i<4;++i) p->z[i].~int();
ptr->~xyx();
// return the raw memory to the system
free(ptr);


Today this is anymore valid C++ code for a variety of reasons (malloc allocates memory without contruction, so in-place construction and explicit in-place destruction are required, in case xyz contains somting other than plain data, like object requiring construction), but to access low level stuff where the memory has to be layed-out in a given way, can still be in use.

More modern C++ code will probably define your struct like
#include <vector>
struct xyz
{
    int x;
    char y;
    std::vector<int> z; //now z is anymore an "array" but a dynamic structure
    // construct by specfying the initial z size
    explicit xyz(size_t vectsize)
        :x(), y(), z(vectsize)
    {}
};


int main()
{
    xyz C(4);
    C.x = 1;
    C.y = 'a';
    c.z[0] = 10;
    c.z[1] = 20;
    c.z[2] = 30;
    c.z[3] = 40;
    /*
     * all other stuffs
     */
    return 0; //destruction is automatic from here
}


But the resultingmemory layout will be completely different (std::vector contains just "pointers" to a dynamically allocated memory)
 
Share this answer
 
v2
Comments
rupeshkp728 21-Dec-11 5:18am    
Thanks Emilio for the explaination.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900