954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

why use of size 0 or 1 array in structure for URI'S etc

Why do some code for eg in gstreamer etc use code which has code like

struct xxx
{
int foo;
...
..
char arrURI[1];
char data[0];
}

ashok.g15
Newbie Poster
4 posts since Dec 2007
Reputation Points: 10
Solved Threads: 0
 

Array indexes start at 0.
char arrURI[1]; -- creates an array of size one
-- so there are two indexes 0 and 1
char data[0]; -- creates an initially empty array
Hope that is what you were looking for.

Grn Xtrm
Posting Pro in Training
495 posts since Nov 2008
Reputation Points: 100
Solved Threads: 48
 

If the array is the last one in the struct, you are probably seeing the struct hack. Prior to C99 it is an unportable trick for allocating arrays in a struct:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char s[1];
} String;

int main()
{
    /* allocate 15 extra bytes for the string */
    String *s = malloc(sizeof *s + 15);

    strcpy(s->s, "test string");
    puts(s->s);
    free(s);

    return 0;
}

The idea is that by tacking on extra memory and accessing it by overflowing the last array member, you can save an extra call to malloc:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char *s;
} String;

int main()
{
    String *s = malloc(sizeof *s);

    s->s = malloc(15);
    strcpy(s->s, "test string");
    puts(s->s);
    free(s->s);
    free(s);

    return 0;
}

C99 makes the struct hack a legal feature of the language, but I do not think it is a good idea even then because it makes the code less clear. ;)

Tom Gunn
Master Poster
733 posts since Jun 2009
Reputation Points: 1,446
Solved Threads: 135
 
Array indexes start at 0. char arrURI[1]; -- creates an array of size one -- so there are two indexes 0 and 1 char data[0]; -- creates an initially empty array Hope that is what you were looking for.


Thank you very much for responding .

As I understand.
from the example I have given
char arrURI[1] ;
is same to declaring
char arrURI;
BOTH allocates only one byte.

But in real usage arrURI is assigned some string which is more than one byte when it is declared as char arrURI[1].

In char data[0];
data is a constant pointer which cannot be assigned another address and data has no size . So how is it equivalent as creating an empty array.

Hope my question is clear.

ashok.g15
Newbie Poster
4 posts since Dec 2007
Reputation Points: 10
Solved Threads: 0
 
char arrURI[1]; -- creates an array of size one -- so there are two indexes 0 and 1


Actually there is only 1 index, which is 0 in char A[1];
A[0] = 'a'; //ok
A[1] = 'b'; //bug

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

In the case of zero sized array, it was generally used as an easy way to index into a variable sized buffer ...

struct Header {
    DWORD dwMagic;
    DWORD dwSize;
    BYTE data[];
};

void MyFunction()
{
    Header *pHdr = (Header *)buffer;
 
    Read(buffer, MAX_SIZE);

    switch(pHdr->dwMagic)
   {
        case M_TAG('R','I','F','F') :
            HandleRIFF(pHdr->data,pHdr->dwSize);
            break;
        // ... etc
   }

}


It lets the compiler calculate the offset so you don't have to.

SVR
Light Poster
45 posts since May 2008
Reputation Points: 10
Solved Threads: 4
 
Actually there is only 1 index, which is 0 in char A[1]; A[0] = 'a'; //ok A[1] = 'b'; //bug


Wow, yes you are right. I mistyped there. Thanks for the correction.
With only one element there is only one index, which is 0.

Grn Xtrm
Posting Pro in Training
495 posts since Nov 2008
Reputation Points: 100
Solved Threads: 48
 

Why can't we just use a pointer. It will do the same
eg : BYTE *byte;

ashok.g15
Newbie Poster
4 posts since Dec 2007
Reputation Points: 10
Solved Threads: 0
 
Why can't we just use a pointer.


In C99 because a pointer might not work while an empty array will. Prior to C99, I cannot think of any reason why an array is better than a pointer except for keeping the array size out of the struct size when using sizeof . I think the original struct hack uses an array size of 0, and it evolved to use 1 for compilers that do not allow an array size of 0.

Tom Gunn
Master Poster
733 posts since Jun 2009
Reputation Points: 1,446
Solved Threads: 135
 
Why can't we just use a pointer. It will do the same eg : BYTE *byte;

Let's try it with my previous example.

struct Header {
    DWORD dwMagic;
    DWORD dwSize;
    BYTE *data;
};

void MyFunction()
{
    Header *pHdr = (Header *)buffer;
 
    Read(buffer, MAX_SIZE);

    switch(pHdr->dwMagic)
   {
        case M_TAG('R','I','F','F') :
            HandleRIFF(pHdr->data,pHdr->dwSize);
            break;
        // ... etc
   }
}


Now this will crash. Why ?

SVR
Light Poster
45 posts since May 2008
Reputation Points: 10
Solved Threads: 4
 
Now this will crash.


An example that actually compiles would help your case. ;)

Tom Gunn
Master Poster
733 posts since Jun 2009
Reputation Points: 1,446
Solved Threads: 135
 

It's purely theoretical. You shouldn't have to compile it to see that it will crash.

The buffer will be filled with unknown data after the first two known values so the four bytes at BYTE *data will be some random value which surely will not be the desired pointer value.
The zero sized array version ->data member will always point to the next byte after the known values in the buffer.

SVR
Light Poster
45 posts since May 2008
Reputation Points: 10
Solved Threads: 4
 
You shouldn't have to compile it to see that it will crash.


All I see is undefined behavior from using a bogus pointer. I have debugged many cases where the same problem does not crash, so your theoretical result does not mean anything unless you can back it up with empirical data. The problem is that saying things like this will crash gives beginners a false sense of security that the program will fail spectacularly if they do something wrong. It is just as probable that the program will fail silently and continue running until the damage done is very costly.

Tom Gunn
Master Poster
733 posts since Jun 2009
Reputation Points: 1,446
Solved Threads: 135
 
All I see is undefined behavior from using a bogus pointer. I have debugged many cases where the same problem does not crash, so your theoretical result does not mean anything unless you can back it up with empirical data. The problem is that saying things like this will crash gives beginners a false sense of security that the program will fail spectacularly if they do something wrong. It is just as probable that the program will fail silently and continue running until the damage done is very costly.

Agreed. Saying it will crash is highly subjective.

I will try to avoid that in the future. I forget that what's 'obvious' to me is not to every one :)

SVR
Light Poster
45 posts since May 2008
Reputation Points: 10
Solved Threads: 4
 
I forget that what's 'obvious' to me is not to every one


We all do. :) For me, obvious now is not always obvious later too. ;)

Tom Gunn
Master Poster
733 posts since Jun 2009
Reputation Points: 1,446
Solved Threads: 135
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You