Thread: illegal zero-sized array

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    3

    illegal zero-sized array

    Hi guys,

    I'm not too familiar with C, and i've got to make some additions to existing code.

    There's a struct defined as

    Code:
    typedef struct _LOG_RECORD 
    {
    
        ULONG Length;           // Length of log record.  This Does not include 
    
        WCHAR Name[];           //  This is a null terminated string
    
    } LOG_RECORD, *PLOG_RECORD;
    The code with the struct compiles without a problem, but as soon as i add an additional WCHAR To[] to the struct.

    Code:
    typedef struct _LOG_RECORD 
    {
    
        ULONG Length;           // Length of log record.  This Does not include 
    
        WCHAR Name[];           //  This is a null terminated string
        WCHAR To[];           //  This is a null terminated string
    
    } LOG_RECORD, *PLOG_RECORD;
    I get the following error : error C2229: struct '_LOG_RECORD' has an illegal zero-sized array.

    If remove the variable "To" again, everything compiles.
    Can anyone please tell my this would be.

    Thank you

  2. #2
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    What is WCHAR defined as? It's not part of C, so it's either a macro or a typedef declared elsewhere.

    Oh, and of course you can't declare an empty array like that unless it's a function parameter. It doesn't make sense. Either give it a size (like WCHAR name[20], or declare it as a pointer, to be assigned later.
    Last edited by cwr; 10-07-2005 at 06:34 AM.

  3. #3
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    its the windows version of wchar_t just like ULONG is their version of unsigned long.

    The problem is that Name[] and To[] try to declare a zero sized array. Why its not throwing up the error on Name[] alone I don't know.

    I'm not sure how the rest of your code uses Name[] and To[] but it can't be good.

  4. #4
    Unregistered User
    Join Date
    Sep 2005
    Location
    Antarctica
    Posts
    341
    I have no idea why it works with Name[], maybe it works if it's the last item in the array only. It would be interesting to see if it broke if you but another variable after Name such as an int or something. Anyway, like cwr said, just make them pointers and you will be fine.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The reason it works with 'Name', is because you're allowed to have arrays declared as such in a structure, so long as it's the last item in the structure. Thus, you can't have multiples.

    [edit]
    6.7.2.1, bullet point 2:

    A structure or union shall not contain a member with incomplete or function type (hence,
    a structure shall not contain an instance of itself, but may contain a pointer to an instance
    of itself), except that the last member of a structure with more than one named member
    may have incomplete array type; such a structure (and any union containing, possibly
    recursively, a member that is such a structure) shall not be a member of a structure or an
    element of an array.
    [/edit]

    Quzah.
    Last edited by quzah; 10-07-2005 at 07:43 AM.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    3
    Thanks for super-quick response!!!

    I changed "To[]" to a "*To" and swapped the order, and now everything compiles. (I'm not sure why though)

    It now looks like
    Code:
    typedef struct _LOG_RECORD 
    {
    
        ULONG Length;           // Length of log record.  This Does not include 
    
        WCHAR *To;           
        WCHAR Name[];           //  This is a null terminated string
        
    } LOG_RECORD, *PLOG_RECORD;
    BTW if I add a "int Something;" afterwards I get the "has an illegal zero-sized array" again.

    But at least it compiles.

  7. #7
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Quote Originally Posted by quzah
    The reason it works with 'Name', is because you're allowed to have arrays declared as such in a structure, so long as it's the last item in the structure. Thus, you can't have multiples.


    Quzah.
    What would be the usefulness of such an array?

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Thantos
    What would be the usefulness of such an array?
    It's a stupid way to have an array with an unspecified size. There's an example some place around here where someone used it for a variable length 'string' structure. Where they allocate via pointer the size of the structure + the length of the string they want. They then use the structure's member as the string, and deallocate with a single free call to the array pointer itself. Like so:
    Code:
    struct foo
    {
        size_t size;
        char somestring[];
    };
    
    ...
    
    struct foo *bar = malloc( SOMESIZE + sizeof *bar );
    strcpy( bar->somestring, "Hello World!" );
    
    ...
    
    free( bar );
    I believe that's how you do it. Personally I don't like it myself. I'd rather malloc the string seperately, but that's just me.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    3
    Interesting. Thanks Quzah!

  10. #10
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Quote Originally Posted by quzah
    It's a stupid way to have an array with an unspecified size.
    Stupid?

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    In my opinion, yes. I find it less intuitive, and unwieldly. What now if I want to allocate an array of these structures? Ah, well you can't. See you can't have an array of such structures, nor can they be members of another structure. That to me doesn't really make them very useful. I suppose if you want to cripple your potential, sure, they could have some use. I just don't like them.

    For one, it's ugly code. It is an ugly allocation, and the use of it is ugly. I don't like ugly code. With a pointer, you know exactly what it is. You also don't have to completely destroy the structure and recreate it if you want to resize its "string" (incomplete array, which for this reference, we were pretending it was a string). If I want to have a larger "string", I have to completely reallocate this structure.

    What if this structure were more complex than just the simple one? Now we have a more complicated reallocation and reasignment of its members.

    It's just not that useful in my opinion, when one can just use a pointer instead. Personal preference. I just don't like them.


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Your dislike of them comes from thinking about them as structures with arrays on the end. But these are actually arrays with structures on the front. It is a perfectly fine generalization of Pascal strings. They are more unfamiliar than ugly.

  13. #13
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    They are generally known as 'flexible arrays'. In C89, structs followed by a variable sized array are often declared as such:
    Code:
    typedef struct _TOKEN_PRIVILEGES {
       DWORD PrivilegeCount;
       LUID_AND_ATTRIBUTES Privileges[1];
    } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
    Flexible arrays were introduced in C99 to provide a 'cleaner' solution. GCC also supports 0 size arrays.

  14. #14
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    zero-sized arrays do not occupy any space within the structure, so sizeof(the structure) is the same both with and without the zero-sized array. Both structures below are both the same size.
    Code:
    struct s1 
    {
    
        long Length;           // Length of log record.  This Does not include 
    
        char Name[];           //  This is a null terminated string
    
    };
    
    struct s2 
    {
    
        long Length;           // Length of log record.  This Does not include 
    
    
    };
    
    int main()
    {
    	cout << sizeof(s1) << " " << sizeof(s2) << endl;
    	return 0;
    }

    you will find them used frequently in VC++ 6.0 include files, such as this one from bhtypes.h. If you don't know what those upper-case data type are -- they are defined in other header files.
    Code:
    
    //=============================================================================
    //  Microsoft (R) Bloodhound (tm). Copyright (C) 1991-1992.
    //
    //  MODULE: bhTypes.h
    //
    //  This is the top-level include file for all Bloodhound struct definitions.
    //=============================================================================
    
    typedef struct _PROPERTYINSTEX
    {
        WORD        Length;         //... length of raw data in frame
        WORD        LengthEx;       //... number of bytes following
        ULPVOID     lpData;         //... pointer to raw data in frame
    
        union
        {
            BYTE            Byte[];     //... table of bytes follows
            WORD            Word[];     //... table of words follows
            DWORD           Dword[];    //... table of Dwords follows
            LARGE_INTEGER   LargeInt[]; //... table of LARGEINT structures to follow
            SYSTEMTIME      SysTime[];  //... table of SYSTEMTIME structures follows
            TYPED_STRING    TypedString;//... a typed_string that may have extended data
        };
    } PROPERTYINSTEX;
    Last edited by Ancient Dragon; 10-07-2005 at 02:07 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  2. 2d array question
    By gmanUK in forum C Programming
    Replies: 2
    Last Post: 04-21-2006, 12:20 PM
  3. question about multidimensional arrays
    By richdb in forum C Programming
    Replies: 22
    Last Post: 02-26-2006, 09:51 AM
  4. Type and nontype parameters w/overloading
    By Mr_LJ in forum C++ Programming
    Replies: 3
    Last Post: 01-02-2004, 01:01 AM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM