473,467 Members | 1,402 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

declaration meaning

Hi all,
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];

thanks,
Krishna

May 5 '06 #1
24 2035
It's illegal. Compiler would complain. If you said for example
char a[1];
it would be one character, and the A would be a pointer to it.
Specifying zero sized arrays is illegal.

May 5 '06 #2
"krishna" <kr************@gmail.com> wrote:
Hi all,
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];


They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};
typedef struct message message_t;

message_t *create_message(int type, int length)
{
message_t *temp;
temp = malloc(length + sizeof(message_t));
if (temp != NULL)
{
temp->type = type;
temp->length = length;
}
return temp;
}

int main()
{
message_t *abc;
abc = create_message(10);
return EXIT_SUCCESS;
}
May 5 '06 #3
If this works, then it's a work of art. :) Of course - if one was to
declare it as a variable, it would get a compiler error. However,
declaring it in a structure doesn't do the allocating itself, we just
get a name we later hold for when referring to (m)allocated memory.
Genialno. :) So, it actually works only for structs?

May 5 '06 #4
thanks for the info
sizeof(message_t) + length is allocated
How can we assign value to the member "data" of the structure message
After the allocation is "data" an character array of size 10?

thanks,
Krishna

May 5 '06 #5
yes actually in the code i am reading it is actually inside the
structure.
Sorry i just mentioned it as a variable

May 5 '06 #6
"krishna" <kr************@gmail.com> wrote:
sizeof(message_t) + length is allocated
How can we assign value to the member "data" of the structure message
After the allocation is "data" an character array of size 10?


Surprisingly, by using data[i], where i is declared as an integer type
and (i >= 0) and (i < 10).
Or any other way allowed by the C language...
May 5 '06 #7
yes it works.
thank u so much!!!

May 5 '06 #8
Roberto Waltman wrote:
"krishna" <kr************@gmail.com> wrote:
Hi all,
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];


They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};


Is this strictly Standard ISO C? I know that GCC allows this form of an
array that forms a variable-length object. C90 wants it to be "char
data[1];" and C99 indicates that is should be "char data[];"
May 5 '06 #9
On Fri, 05 May 2006 14:20:26 -0400, Roberto Waltman
They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};
typedef struct message message_t;

message_t *create_message(int type, int length)
{
message_t *temp;
temp = malloc(length + sizeof(message_t));
if (temp != NULL)
{
temp->type = type;
temp->length = length;
}
return temp;
}

int main()
{
message_t *abc;
abc = create_message(10); Sorry, this call should have two parameters, of course.
return EXIT_SUCCESS;
}


I think I misunderstood Krishna's 2nd question.
In this example the array could be accessed as
abc->data, abc->data[5], etc.
(If abc is not NULL).
May 5 '06 #10


void * clvrmnky() wrote On 05/05/06 15:18,:
Roberto Waltman wrote:
"krishna" <kr************@gmail.com> wrote:

Hi all,
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];


They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};

Is this strictly Standard ISO C?


No.

--
Er*********@sun.com

May 5 '06 #11
On Fri, 05 May 2006 15:18:52 -0400, "void * clvrmnky()"
<cl**************@hotmail.com.invalid> wrote:
Roberto Waltman wrote:
"krishna" <kr************@gmail.com> wrote:
Hi all,
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];


They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};


Is this strictly Standard ISO C? I know that GCC allows this form of an
array that forms a variable-length object. C90 wants it to be "char
data[1];" and C99 indicates that is should be "char data[];"


No. Thanks for pointing this out. From ISO/IEC-9899 2nd edition:

"6.7.5.2 Array declarators
Constraints
1 In addition to optional type qualifiers and the keyword static, the
[ and ] may delimit an expression or *. If they delimit an expression
(which specifies the size of an array), the expression shall have an
integer type. If the expression is a constant expression, it shall
have a value greater than zero."

May 5 '06 #12
Roberto Waltman <us****@rwaltman.net> writes:
"krishna" <kr************@gmail.com> wrote:
char a[10];
will declare character array of size 10 starting with the index 0.
what is the meaning of the following declaration? what is the purpose
of such
declarations?
char a[0];
They are used sometimes to provide a name for a variable size array,
located at the adress of 'a'.
For example:

[...]
struct message
{
int type;
int length;
char data[0];
};

[...]

This is not legal in standard C, though some compilers may allow it as
an extension. Another common way to express this is by declaring
char data[1];

Both forms are known as the "struct hack". C99 provides a new
features called "flexible array members", intended to provide the
functionality of the struct hack in a clearly legal manner.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 5 '06 #13
"Darko" <da**************@gmail.com> writes:
If this works, then it's a work of art. :) Of course - if one was to
declare it as a variable, it would get a compiler error. However,
declaring it in a structure doesn't do the allocating itself, we just
get a name we later hold for when referring to (m)allocated memory.
Genialno. :) So, it actually works only for structs?


What are you talking about?

Please read <http://cfaj.freeshell.org/google/>.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 5 '06 #14
Darko wrote:

If this works, then it's a work of art. :) Of course - if one was to
declare it as a variable, it would get a compiler error. However,
declaring it in a structure doesn't do the allocating itself, we just
get a name we later hold for when referring to (m)allocated memory.
Genialno. :) So, it actually works only for structs?


Very clear. It is obvious to all what 'it' means. I suggest you
try reading your own posts before hitting the equivalent of a
'send' key, and seeing if it makes sense. Without context most
posts do not. To include suitable context, even with the insipidly
stupid google interface to usenet, see my sig. below.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
May 5 '06 #15
i try the code in vs.net,it can not pass.
does it only work in gcc?

May 6 '06 #16
da**************@gmail.com wrote:
i try the code in vs.net,it can not pass.
does it only work in gcc?

Please quote context.

The code will not compile in gcc (create_message is only called with one
parameter), the struct will compile with a warning.

Other compilers will correctly reject it.

--
Ian Collins.
May 6 '06 #17
#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};
typedef struct message message_t;

message_t *create_message(int type, int length)
{
message_t *temp;
temp = malloc(length + sizeof(message_t));
if (temp != NULL)
{
temp->type = type;
temp->length = length;
}
return temp;
}

int main()
{
message_t *abc;
abc = create_message(10);
return EXIT_SUCCESS;
}

In C, we can declare arrays of objects as follows:

message array[4];

And we're guaranteed that each element is DIRECTLY after the other in
memory, such that we can use a pointer like so:

message *p = &array[0];
++p; //now it points to the 2nd element
++p; //now it points to the 3rd element
++p; //now it points to the 4th element

To facilitate this, the "sizeof" operator returns the full size of the
struct including any necessary padding at the end, such that the next
element in an array can be directly after it.

So, if you define a struct as follows:

struct Monkey { int i; int k; char b; };

It is very probable that it will take up the following amount of memory:

a) 4 bytes for "i"
b) 4 bytes for "k"
b) 1 byte for "b"
c) 3 bytes of padding so the next element can be right after it.

This gives us an overall size of 12 bytes.

Now here's my question:

If we define a structure which has an array at the end of it, how can we be
sure that there's no padding at the end?

-Tomás
May 6 '06 #18
In article <S7******************@news.indigo.ie>, Tomás <NU**@NULL.NULL> wrote:
Now here's my question: If we define a structure which has an array at the end of it, how can we be
sure that there's no padding at the end?


( ( (char *) &structname + sizeof structname) -
( (char *) &structname.arrayname + sizeof structname.arrayname ) ) == 0

This should be legal because you are allowed to construct pointers
to one element past the end of an object. If I recall a posting
from a few weeks ago correctly, C99 specifically indicates that
such pointers are comparable (so you could test them for
equality instead of subtracting them), but if I remember correctly,
C89 does not specifically indicate you can compare such pointers
to each other [which is why I take their difference, with the
potentially larger value first]

--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson
May 6 '06 #19
Tomás wrote:
#include <stdlib.h>

struct message
{
int type;
int length;
char data[0];
};
typedef struct message message_t;

message_t *create_message(int type, int length)
{
message_t *temp;
temp = malloc(length + sizeof(message_t));
if (temp != NULL)
{
temp->type = type;
temp->length = length;
}
return temp;
}

int main()
{
message_t *abc;
abc = create_message(10);
return EXIT_SUCCESS;
}

In C, we can declare arrays of objects as follows:

message array[4];

And we're guaranteed that each element is DIRECTLY after the other in
memory, such that we can use a pointer like so:

message *p = &array[0];
++p; //now it points to the 2nd element
++p; //now it points to the 3rd element
++p; //now it points to the 4th element

To facilitate this, the "sizeof" operator returns the full size of the
struct including any necessary padding at the end, such that the next
element in an array can be directly after it.

So, if you define a struct as follows:

struct Monkey { int i; int k; char b; };

It is very probable that it will take up the following amount of memory:

a) 4 bytes for "i"
b) 4 bytes for "k"
b) 1 byte for "b"
c) 3 bytes of padding so the next element can be right after it.

This gives us an overall size of 12 bytes.

Now here's my question:

If we define a structure which has an array at the end of it, how can we be
sure that there's no padding at the end?

-Tomás


Why do you care that there's padding? sizeof tells you all you need to
know doesn't it?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
May 6 '06 #20
Why do you care that there's padding? sizeof tells you all you need to
know doesn't it?


Well consider this:

(I'm still not adjusted to C, so forgive me if I use C++ idioms/styles which
I shouldn't use.)

#include <stdlib.h>

typedef struct Monkey {

int i;
char a[1];

} Monkey;

void SomeFunc( Monkey* const p_monkey )
{
/* Let's get a pointer to the second array element: */

char *pc1 = &p_monkey->a[1];
/* Now let's do that another way: */

char *pc2 = (char*) (p_monkey + 1);
/* ******************************** */
/* Now let's compare the addresses */

if ( pc1 != pc2 )
{
printf("We have padding at the end!");
}
}

int main(void)
{
//Let's say we want that array to
//consist of seven elements:

void* const p = malloc( sizeof(Monkey) + 6 );

Monkey* const p_monkey = (Monkey*)p;

p_monkey->i = 5;

p_monkey->a[0] = 'a';
p_monkey->a[1] = 'b';
p_monkey->a[2] = 'c';
p_monkey->a[3] = 'd';
p_monkey->a[4] = 'e';
p_monkey->a[5] = 'f';
p_monkey->a[6] = 'g';

SomeFunc( p_monkey );
free(p);
}
If there is indeed three bytes of padding at the end of this structure, then
the following l-value:

p_monkey->a[1]

refers to the first byte of padding.

However, the following l-value:

p_monkey + 1

refers to the first byte AFTER the three bytes of padding.

Therefore, it seems that there's not much benefit in the whole "array at the
end of a structure" strategy. It would be just as handy to do the following:
typedef struct Monkey { int i; } Monkey;

int main(void)
{
void* const p = malloc( sizeof(Monkey) + 7 );
Monkey* const p_monkey = (Monkey*)p;
/* Now if we want to access the array: */

char* p_array = (char*) (p_monkey + 1);

p_array[0] = 'a';

p_array[1] = 'b';
}
Then "SomeFunc" could play with the structure as follows:
void SomeFunc( Monkey* const p_monkey )
{
/* Let's get a pointer to the first array element: */

char *p = (char*) (p_monkey + 1);

/* Now access the array: */

p[0] = 'a';
}

It appears to me, that there would only be merit in the method of putting an
array at then end of a struct if the padding was put BEFORE the first array
element, as follows:

a) 4 bytes for "i"
b) 3 bytes of padding.
c) 1st element of the array.
-Tomás
May 6 '06 #21
And this difference depends upon how the Monkey structure is defined
(specifically, the length we specify for "array").

Opps I just realized that your code was correct, and that it took into
account the length we specify for "arrayname". I'll try again:

enum { length = 5; };

typedef struct Monkey { int i; char array[length]; } Monkey;

enum bool { false, true };

bool IsTherePaddingAtTheEndOfMonkey(void)
{
Monkey object;

void* const p1 = &object + 1;

void* const p2 = &object.array + 1;

if ( p1 != p2 ) printf( "We have padding!";

/* The amount of padding is determined by: */

(char*)p1 - (char*)p2;
}
-Tomás
May 6 '06 #22
On 2006-05-06, Tomás <NU**@NULL.NULL> wrote:
Why do you care that there's padding? sizeof tells you all you need to
know doesn't it?

[...]
If there is indeed three bytes of padding at the end of this structure, then
the following l-value:

p_monkey->a[1]

refers to the first byte of padding.

However, the following l-value:

p_monkey + 1

refers to the first byte AFTER the three bytes of padding.
Yes (a few operators and casts understood), but that doesn't really
matter so long as you don't try to use p_monkey + 1 to find the second
element of the array, but always use p_monkey->a[1].

It means you malloc a bit more than you need-- sizeof (Monkey) + 7
extends the array actually by 7 + padding. But that doesn't really
matter.
Therefore, it seems that there's not much benefit in the whole "array at the
end of a structure" strategy. It would be just as handy to do the following:
typedef struct Monkey { int i; } Monkey;

int main(void)
{
void* const p = malloc( sizeof(Monkey) + 7 );
Monkey* const p_monkey = (Monkey*)p;
/* Now if we want to access the array: */

char* p_array = (char*) (p_monkey + 1);

p_array[0] = 'a';

p_array[1] = 'b';
}
Yes, this also works. Then you wouldn't bother with the char a[1] at the
end of struct Monkey presumably. It would be positively misleading to
leave it in there.

It's less convenient this way though, because you have to use casts to
get at that array, and the user of the array (SomeFunc say) has to know
what type to cast to. If we have that char a[1], we know at least that
it's an array of char (or whatever else), and we just use it
transparently as if it were a larger array.
Then "SomeFunc" could play with the structure as follows:
void SomeFunc( Monkey* const p_monkey )
{
/* Let's get a pointer to the first array element: */

char *p = (char*) (p_monkey + 1);

/* Now access the array: */

p[0] = 'a';
} It appears to me, that there would only be merit in the method of
putting an array at then end of a struct if the padding was put BEFORE
the first array element, as follows:

a) 4 bytes for "i"
b) 3 bytes of padding.
c) 1st element of the array.


This sounds like it could work, and I think the compiler could
legitimately do it that way if it felt like it; then (p_monkey + 1 ==
&p_monkey->array[1]). But it doesn't matter in practice that these are
not equal, so long as you don't use p_monkey + 1 to get to the second
element of the extended array.
May 6 '06 #23
Darko schrieb:
If this works, then it's a work of art. :) Of course - if one was to
declare it as a variable, it would get a compiler error. However,
declaring it in a structure doesn't do the allocating itself, we just
get a name we later hold for when referring to (m)allocated memory.
Genialno. :) So, it actually works only for structs?

work of art? I'd say that's a landmine.

- Anyone unsuspiciously using a memcpy(pX,pFoo,sizeof(*pFoo)) will get
surprising results.

- Using malloc, one must take into account that the storage for the
first element is covered by sizeof(stuct message) while the rest is not.

- for copying you should at least provide a size_t len member to
determine the "extra" space.

- it makes your code wide open for heap-overflow attacks and code
injection exploits.

- It's impossible to have these objects on the stack, even if the
compiler permits it.

- Consider using #pragma pack(1) struct ... #pragma pack()
this will provide you at least with defined memory-layouts you are using
reinterpret-casts to the "char" data, even if packing was modified from
somewhere else. (cc options, foreign headers)

I'd suggest not to use this construct even if it's convenient.

<flame mode="plenty">
variable sized array are pure evil
</flame>
May 7 '06 #24
michi <sp**@reppisch.de> writes:
Darko schrieb:
If this works, then it's a work of art. :) Of course - if one was to
declare it as a variable, it would get a compiler error. However,
declaring it in a structure doesn't do the allocating itself, we just
get a name we later hold for when referring to (m)allocated memory.
Genialno. :) So, it actually works only for structs?
work of art? I'd say that's a landmine.


The technique described in the previous article is the "struct hack",
a very well-known technique. C99 adds "flexible array members" (q.v.)
that do the same thing.
- Anyone unsuspiciously using a memcpy(pX,pFoo,sizeof(*pFoo)) will get
surprising results.
Yes, you have to be careful.
- Using malloc, one must take into account that the storage for the
first element is covered by sizeof(stuct message) while the rest is
not.
Yes.
- for copying you should at least provide a size_t len member to
determine the "extra" space.
Yes.
- it makes your code wide open for heap-overflow attacks and code
injection exploits.
How so? If you manage memory carefully enough, this shouldn't be an
issue.
- It's impossible to have these objects on the stack, even if the
compiler permits it.
Yes.
- Consider using #pragma pack(1) struct ... #pragma pack()
this will provide you at least with defined memory-layouts you are
using reinterpret-casts to the "char" data, even if packing was
modified from somewhere else. (cc options, foreign headers)


"#pragma pack" is non-standard and non-portable. Use it if you must,
but I don't see how it helps in using the "struct hack". (And C
doesn't have "reinterpret-casts"; that's a C++ term.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 8 '06 #25

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

83
by: Alexander Zatvornitskiy | last post by:
Hello All! I'am novice in python, and I find one very bad thing (from my point of view) in language. There is no keyword or syntax to declare variable, like 'var' in Pascal, or special syntax in...
4
by: Razvan | last post by:
Hi ! Consider the following XML element: <!ELEMENT value (#PCDATA)> <!ATTLIST value year CDATA #IMPLIED>
3
by: Alexander Farber | last post by:
Hi, does anyone have an idea, why do I get the following error (I have to use g++296 on RedHat Linux as compiler): In file included from r_dir.cpp:9: r_obey.h:262: declaration of `const...
5
by: vilhelm.sjoberg | last post by:
Hello, I am a resonably confident C programmer, but not very sure about the dark corners of C++. Recently, I had G++ give me a strange error. The program in question is in essence: struct...
10
by: Kobu | last post by:
My question is about the use and meaning of the terms "declaration" and "definition" as it pertains to the C language. I've read sources that mix the two up when talking about such things as...
2
by: nick | last post by:
the following is my programming code and compile message why the warning message arise, have i done somethings wrong? #include<stdio.h> typedef struct card{ int abc; }card;
9
by: Michael Mair | last post by:
Hello, in C89 (at least in the last public draft), "3.6.2 Compound statement, or block", we have ,--- | Syntax | | compound-statement: | { ...
5
by: ditwal001 | last post by:
hi folks which datatype declaration is to be preferred in c# .net? ex. System.String sTemp = ""; System.Int64 = 0; or
4
by: the_init | last post by:
Hi friends, Can you please explain me why the following code prints 10, instead of 20 - Here I am little confused with the static and global declaration of i in the same program. ...
9
by: Jess | last post by:
Hello, I was told that if I declare a static class constant like this: class A{ static const int x = 10; }; then the above statement is a declaration rather than a definition. As I've...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.