473,326 Members | 2,337 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

What does the array do?

Recently I have come across a number of struct's that I think is quite
interesting:

typedef struct whatever_tag
{
int member1;
char member2;
// ...

char last_member[1]; // interesting line
} whatever;

My quetions is, why an array of size 1 instead of just a single object?
It looks like C code instead of C++ though, hope it's not off-topic.

Ben
Feb 12 '06 #1
11 1904
* benben:
Recently I have come across a number of struct's that I think is quite
interesting:

typedef struct whatever_tag
{
int member1;
char member2;
// ...

char last_member[1]; // interesting line
} whatever;

My quetions is, why an array of size 1 instead of just a single object?
It looks like C code instead of C++ though, hope it's not off-topic.


It is indeed C code. The idea is to do something like

whatever* w = malloc( offsetof( whatever, last_member ) + n_items ) );
w->last_member[n_items-1] = something;

In C++ make last_member a std::vector, for example.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 12 '06 #2
benben wrote:
Recently I have come across a number of struct's that I think is quite
interesting:

typedef struct whatever_tag
{
int member1;
char member2;
// ...

char last_member[1]; // interesting line
} whatever;

My quetions is, why an array of size 1 instead of just a single
object? It looks like C code instead of C++ though, hope it's not
off-topic.


It is often better to ask in comp.lang.c about any C construct.

In good old times, to create a structure with "dynamic" part you would
declare an array of 1, like above, then allocate (using 'malloc') more
than (sizeof(whatever)) by a certain number of bytes. Once allocated,
such structure would be considered to contain an array of 'certain number
of bytes' at its end, and not an array of 1. Since indexing is not part
of array semantics, but instead a pointer thing, you could write:

whatever *pw = (whatever*) malloc(sizeof(whatever) + 150);
pw->last_member[100] = 42;

and it would be OK.

This practice has been essentially replaced by several techniques in C++.
You can have a template with a template-argument-sized array, you can
have a class that dynamically allocates part of it, etc.

The advantage of using this old C trick is that the memory for that
array is right there, essentially _in_ the object (convenient for the
purposes of, say, serialization). The disadvantage is that you have
to store the size of the object in the object.

V
--
Please remove capital As from my address when replying by mail
Feb 12 '06 #3
* Victor Bazarov, doing C:

whatever *pw = (whatever*) malloc(sizeof(whatever) + 150);


In C, casting the result of malloc is Evil. One reason is that if the
relevant #include for malloc has been omitted, the cast may do Very
Unholy Things, where the malloc result pointer is converted to an int
which is in turn converted to a typed pointer, with no diagnostic. In
C++ we have stronger typing and hence in C++ the cast should be there,
if for any reason we'd choose to use C malloc instead of C++ new.

Cheers,

- ALf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 12 '06 #4
> The advantage of using this old C trick is that the memory for that
array is right there, essentially _in_ the object (convenient for the
purposes of, say, serialization). The disadvantage is that you have
to store the size of the object in the object.

V


Thank you for the reply!

If I am not too far off I guess with this trick only the first element
in the array can be properly destroyed if it has a destructor?

Ben
Feb 12 '06 #5
On Sun, 12 Feb 2006 02:04:07 +0100, "Alf P. Steinbach"
<al***@start.no> wrote:
* Victor Bazarov, doing C:

whatever *pw = (whatever*) malloc(sizeof(whatever) + 150);


In C, casting the result of malloc is Evil. One reason is that if the
relevant #include for malloc has been omitted, the cast may do Very
Unholy Things, where the malloc result pointer is converted to an int
which is in turn converted to a typed pointer, with no diagnostic.


Interesting point of view. AFAIK, ANSI-C requires a prototyp for a
function, otherwise it should not compile. Moreover, the return value
of malloc is a void* and it's usually considered good style to use an
explicit cast when you cast from void* and not rely on the implicit
cast (that is possible in C).

Regards,
Roland Pibinger
Feb 12 '06 #6
* Roland Pibinger:
On Sun, 12 Feb 2006 02:04:07 +0100, "Alf P. Steinbach"
<al***@start.no> wrote:
* Victor Bazarov, doing C:
whatever *pw = (whatever*) malloc(sizeof(whatever) + 150); In C, casting the result of malloc is Evil. One reason is that if the
relevant #include for malloc has been omitted, the cast may do Very
Unholy Things, where the malloc result pointer is converted to an int
which is in turn converted to a typed pointer, with no diagnostic.


Interesting point of view.


Well, it's a FAQ (C FAQ item 7.7b) -- so perhaps it's interesting! ;-)
See <url: http://c-faq.com/malloc/mallocnocast.html>.

AFAIK, ANSI-C requires a prototyp for a
function, otherwise it should not compile.
Nope. It may be so in C99. But according to <url:
http://www.cpax.org.uk/prg/writings/casting.php> (I'm just throwing in a
typical web page discussing this, other than the C FAQ) section 3.3.2.2
of the ANSI C Standard of 1989 states:

<quote>
If the expression that precedes the parenthesized argument list
in a function call consists solely of an identifier, and if no
declaration is visible for this identifier, the identifier is
implicitly declared exactly as if, in the innermost block
containing the function call, the declaration

extern int identifier();

appeared.
</quote>

Moreover, the return value of malloc is a void*
Nope, not if you don't have a declaration; then it's an int (see above).

and it's usually considered good style to use an
explicit cast when you cast from void* and not rely on the implicit
cast (that is possible in C).


Nope.

Cheers, and hope this helps,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 12 '06 #7

"benben" <be******@yahoo.com.au> skrev i meddelandet
news:43**********************@news.optusnet.com.au ...
The advantage of using this old C trick is that the memory for that
array is right there, essentially _in_ the object (convenient for
the
purposes of, say, serialization). The disadvantage is that you
have
to store the size of the object in the object.

V


Thank you for the reply!

If I am not too far off I guess with this trick only the first
element in the array can be properly destroyed if it has a
destructor?


It's a C thing, so it doesn't have a destructor. :-)
If you put non-POD C++ objects in the struct, you open a whole new can
of worms.

Please don't do that! :-)
Bo Persson
Feb 12 '06 #8
Roland Pibinger wrote:
On Sun, 12 Feb 2006 02:04:07 +0100, "Alf P. Steinbach"
<al***@start.no> wrote:
* Victor Bazarov, doing C:

whatever *pw = (whatever*) malloc(sizeof(whatever) + 150);


In C, casting the result of malloc is Evil. One reason is that if
the relevant #include for malloc has been omitted, the cast may do
Very Unholy Things, where the malloc result pointer is converted to
an int which is in turn converted to a typed pointer, with no
diagnostic.


Interesting point of view. AFAIK, ANSI-C requires a prototyp for a
function, otherwise it should not compile. Moreover, the return value
of malloc is a void* and it's usually considered good style to use an
explicit cast when you cast from void* and not rely on the implicit
cast (that is possible in C).


As Alf says in his follow-up, the prototype requirement didn't come
into play until C99. Prior to that, implicit declarations were
possible. As to your second contention, it is the general consensus on
comp.lang.c that it is BAD style to use unnecessary casts, especially
when such casts may hide serious programming errors. Covering up a
mismatch between declaration and implementation is generally considered
a serious problem.

Brian

Feb 12 '06 #9
On Sun, 12 Feb 2006 13:03:33 +0100, "Alf P. Steinbach"
<al***@start.no> wrote:
according to <url:
http://www.cpax.org.uk/prg/writings/casting.php> (I'm just throwing in a
typical web page discussing this, other than the C FAQ) section 3.3.2.2
of the ANSI C Standard of 1989 states:

<quote>
If the expression that precedes the parenthesized argument list
in a function call consists solely of an identifier, and if no
declaration is visible for this identifier, the identifier is
implicitly declared exactly as if, in the innermost block
containing the function call, the declaration

extern int identifier();

appeared.
</quote>


You are right. K&R use prototypes permanently and emphasize their
importance several times in the book. Hence the false impression. But
C-Compilers usually issue a warning for undeclared functions.

Regards,
Roland Pibinger
Feb 12 '06 #10

"benben" <be******@yahoo.com.au> wrote in message
news:43***********************@news.optusnet.com.a u...
Recently I have come across a number of struct's that I think is quite
interesting:

typedef struct whatever_tag
{
int member1;
char member2;
// ...

char last_member[1]; // interesting line
} whatever;

My quetions is, why an array of size 1 instead of just a single object?
It looks like C code instead of C++ though, hope it's not off-topic.

Ben


As some of the other posting have explained, the array is so that you can
tag on a
dynamic piece of memory to the basic structure. However, I think the [1] is
slightly incorrect,
typically this should be [0]. If the intent of the structure is what we have
assumed, you'd
be wasting one char on each structure (unless some special logic has been
used to allocate
a malloc'd array one char too small and similar convoluted logic has been
used to access
the array). Might be because some compilers will detect you are indexing
into a zero
sized array ?
Feb 12 '06 #11
* Dave Townsend:
* benben:
Recently I have come across a number of struct's that I think is quite
interesting:

typedef struct whatever_tag
{
int member1;
char member2;
// ...

char last_member[1]; // interesting line
} whatever;

My quetions is, why an array of size 1 instead of just a single object?
It looks like C code instead of C++ though, hope it's not off-topic.


As some of the other posting have explained, the array is so that you can
tag on a dynamic piece of memory to the basic structure. However, I think
the [1] is slightly incorrect, typically this should be [0].


In C++ an array size of 0 is invalid, and requires a diagnostic from the
compiler. Before the template way like BOOST_STATIC_ASSERT using arrays
size 0 to implement a kind of static assert was not unusual. I don't
know whether an array size of 0 is valid in C, or not.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 13 '06 #12

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

Similar topics

4
by: F. Da Costa | last post by:
Hi, I was wondering whether someone could enlighten me as to the reason why the slice does not work in IE when the arr is passed in properly. Checked the values in the srcArr and they are...
140
by: Oliver Brausch | last post by:
Hello, have you ever heard about this MS-visual c compiler bug? look at the small prog: static int x=0; int bit32() { return ++x; }
24
by: David Mathog | last post by:
If this: int i,sum; int *array; for(sum=0, i=0; i<len; i++){ sum += array; } is converted to this (never mind why for the moment):
6
by: Niklaus | last post by:
Hi, Can someone point out what is wrong with this code ? How can i make it better optimize it. When run it gives me seg fault in linux. But windows it works fine(runs for a long time). Do we...
18
by: Matt | last post by:
Hi, I have a probelm here: If I declare: char *p="Hello";
13
by: Jason Huang | last post by:
Hi, Would someone explain the following coding more detail for me? What's the ( ) for? CurrentText = (TextBox)e.Item.Cells.Controls; Thanks. Jason
14
by: Bit byte | last post by:
Came accross the ff code: double array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector<double> values(array, array + 9); //<- is this a 2D vector ?
5
by: Cylix | last post by:
this.menus = { root: new Array };
5
by: Mercy | last post by:
I guess my C++ is pretty darn rusty. I was just looking over sample C++ code for practice... and I'm kind of confused about this code fragment: int sector2; int i = 3; memset(sector2,...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.