473,671 Members | 2,121 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

compound literals

What is the point of them?

When should I use them?

They seem to be rather useless but hopefully someone can prove me
wrong. I think they are just additions to c99 but didn't exist in
c89/90.
Also, when is it appropriate to cast? Casting seems to be frowned up
on so it makes me wonder when it is appropriate to ever cast.
Nov 13 '05 #1
3 3422
On 13 Sep 2003 22:35:51 -0700, ne*****@tokyo.c om (Mantorok Redgormor)
wrote:
What is the point of them?

When should I use them?


Passing an argument to a function without using a temporary:

foo( (struct bar){ 1, 2 } );

Adding storage qualifiers:

(const char[]){ "foo" }

Nick.

Nov 13 '05 #2
In message <41************ **************@ posting.google. com>
ne*****@tokyo.c om (Mantorok Redgormor) wrote:
What is the point of them?

When should I use them?

They seem to be rather useless but hopefully someone can prove me
wrong. I think they are just additions to c99 but didn't exist in
c89/90.
They are new in C99 (and hence don't exist in C++ either).

They're not a massively useful construct, but when you do find an application
for them, they can help tidy up code quite well. Here are two real-life
examples, from some SCSI software:

/* Array literal constants defining well-known SCSI commands */
#define CDB_TEST_READY ((const uint8_t[6]) { 0x00 })
#define CDB_INQUIRY_L ((const uint8_t[6]) { 0x12, 0, 0, 0, 36, 0 })
#define CDB_CAPACITY ((const uint8_t[10]) { 0x25 })

With these defines, a whole SCSI command can be simply defined and passed
to an API by giving the macro name, without having to manually declare and
initialise a variable.

Now a more complex example, which will lead in nicely to your cast question.
The software internally uses error codes (from 0-255), but has to supply the
outside world with a pointer to an error structure (consisting of a code,
followed by a variable length string). A simple (!) form of knocking up a
mapping table, ignoring internationalis ation issues, can work as follows:

--- errors.h ---

// typedef struct { int errnum; char errmess[252]; } oserror;

#define SCSI_ErrorBase 0x20100

enum
{
SCSI_NoRoom = 0x00,
SCSI_SWIunkn,
SCSI_RCunkn,
...
};

oserror *scsi_error(uns igned err);

--- errors.c ---

#define ErrType(str) const struct { int errnum; char errmess[sizeof str]; }
#define ErrBlock(num, str) (ErrType(str)) { num, str }
#define ErrEntry(num, str) [num] = (oserror *) &ErrBlock(SCSI_ ErrorBase+num,s tr)

static oserror * const errtable[256] =
{
ErrEntry(SCSI_N oRoom, "No room for SCSI driver workspace"),
ErrEntry(SCSI_S WIunkn, "Unknown SCSI SWI number"),
ErrEntry(SCSI_R Cunkn, "Unknown reason code for SCSI SWI"),
...
};

oserror *scsi_error(uns igned err)
{
if (err >= 256) return (oserror *) err;

if (errtable[err]) return errtable[err];

return scsi_error(SCSI _InvalidParms);
}

If you pick through the macro definitions, you'll note that this also uses
designated initialisers, another C99 feature, to match the errtable array
entries to the enum. Also be aware that the code is not portable for other
reasons (mentioned below).
Also, when is it appropriate to cast? Casting seems to be frowned up
on so it makes me wonder when it is appropriate to ever cast.


Casting is generally frowned upon, yes, as it is usually unnecessary - if you
find yourself needing to cast you're probably doing something non-portable or
you're patching over an error. Here are some examples, in ascending order of
frown-factor.

It can be used straightforward ly to perform a conversion (eg manually
converting a float to an int), but this is usually not required, as implicit
conversions happen on assignment and when passing values to prototyped
functions. You might need casts in expressions; one valid example might be:

int m = <whatever>, n = <whatever>;
float ratio = (float) m / (float) n;

Without the casts, the division would be performed as an integer division.

It can be used to fudge qualifiers like "const" - for example a definition of
strchr (from <string.h>) would have to have a cast to coerce the "const char
*" passed in into a returned "char *".

It can be used to change the interpretation of a pointer (eg the cast of the
arbitrary sized compound literal to oserror * in the ErrEntry macro above) -
this sort of casting is only valid if you know that the thing being pointed
to can be accessed through the new type of pointer; C gives some assurances
about when this works, eg when structures have common initial members, but
otherwise you have to be careful when writing portable code.

Most dubiously, you can convert between fundamentally different types - eg
the cast of an unsigned to an oserror * in the scsi_error function. That is
definitely non-portable. Don't do it.

--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
Nov 13 '05 #3
Kevin Bracey <ke**********@t ematic.com> wrote in message news:<07******* *********@temat ic.com>...
In message <41************ **************@ posting.google. com>
ne*****@tokyo.c om (Mantorok Redgormor) wrote:
What is the point of them?

When should I use them?

They seem to be rather useless but hopefully someone can prove me
wrong. I think they are just additions to c99 but didn't exist in
c89/90.


They are new in C99 (and hence don't exist in C++ either).

They're not a massively useful construct, but when you do find an application
for them, they can help tidy up code quite well. Here are two real-life
examples, from some SCSI software:

/* Array literal constants defining well-known SCSI commands */
#define CDB_TEST_READY ((const uint8_t[6]) { 0x00 })
#define CDB_INQUIRY_L ((const uint8_t[6]) { 0x12, 0, 0, 0, 36, 0 })
#define CDB_CAPACITY ((const uint8_t[10]) { 0x25 })

With these defines, a whole SCSI command can be simply defined and passed
to an API by giving the macro name, without having to manually declare and
initialise a variable.

Now a more complex example, which will lead in nicely to your cast question.
The software internally uses error codes (from 0-255), but has to supply the
outside world with a pointer to an error structure (consisting of a code,
followed by a variable length string). A simple (!) form of knocking up a
mapping table, ignoring internationalis ation issues, can work as follows:

--- errors.h ---

// typedef struct { int errnum; char errmess[252]; } oserror;

#define SCSI_ErrorBase 0x20100

enum
{
SCSI_NoRoom = 0x00,
SCSI_SWIunkn,
SCSI_RCunkn,
...
};

oserror *scsi_error(uns igned err);

--- errors.c ---

#define ErrType(str) const struct { int errnum; char errmess[sizeof str]; }
#define ErrBlock(num, str) (ErrType(str)) { num, str }
#define ErrEntry(num, str) [num] = (oserror *) &ErrBlock(SCSI_ ErrorBase+num,s tr)

static oserror * const errtable[256] =
{
ErrEntry(SCSI_N oRoom, "No room for SCSI driver workspace"),
ErrEntry(SCSI_S WIunkn, "Unknown SCSI SWI number"),
ErrEntry(SCSI_R Cunkn, "Unknown reason code for SCSI SWI"),
...
};

oserror *scsi_error(uns igned err)
{
if (err >= 256) return (oserror *) err;

if (errtable[err]) return errtable[err];

return scsi_error(SCSI _InvalidParms);
}

If you pick through the macro definitions, you'll note that this also uses
designated initialisers, another C99 feature, to match the errtable array
entries to the enum. Also be aware that the code is not portable for other
reasons (mentioned below).
Also, when is it appropriate to cast? Casting seems to be frowned up
on so it makes me wonder when it is appropriate to ever cast.


Casting is generally frowned upon, yes, as it is usually unnecessary - if you
find yourself needing to cast you're probably doing something non-portable or
you're patching over an error. Here are some examples, in ascending order of
frown-factor.

It can be used straightforward ly to perform a conversion (eg manually
converting a float to an int), but this is usually not required, as implicit
conversions happen on assignment and when passing values to prototyped
functions. You might need casts in expressions; one valid example might be:

int m = <whatever>, n = <whatever>;
float ratio = (float) m / (float) n;

Without the casts, the division would be performed as an integer division.

It can be used to fudge qualifiers like "const" - for example a definition of
strchr (from <string.h>) would have to have a cast to coerce the "const char
*" passed in into a returned "char *".

It can be used to change the interpretation of a pointer (eg the cast of the
arbitrary sized compound literal to oserror * in the ErrEntry macro above) -
this sort of casting is only valid if you know that the thing being pointed
to can be accessed through the new type of pointer; C gives some assurances
about when this works, eg when structures have common initial members, but
otherwise you have to be careful when writing portable code.

Most dubiously, you can convert between fundamentally different types - eg
the cast of an unsigned to an oserror * in the scsi_error function. That is
definitely non-portable. Don't do it.


Thanks for the great post! Very informative.
Nov 13 '05 #4

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

Similar topics

4
4433
by: Sonia | last post by:
I have been looking for a definition of a compound class but cannot find it anywhere ? What exactly is a compound class ? Thanks
4
3995
by: Mark | last post by:
BEGINNER QUESTION I have a table which has a compound primary key consisting of two columns. One of these columns is a foreign key which is generated in another table by an identity. I want to be able to generate the other primary key column value automatically when an insert occurs but assume that I cannot use an identity because it would have to be unique for this table.
6
3735
by: David W. Fenton | last post by:
I'm generally against using compound keys, except in join tables, but I'm currently mapping out a schema where the join table has child records. The application is for fund-raising and I have four relevant tables: tblPerson tblOutreach -- the list of fund-raising actions/events (letters, events, etc.) To join these two tables, I have:
6
2663
by: William Ahern | last post by:
So, GCC 4.01 is giving errors that GCC 3.3 did not, and I'm thinking they've gone overboard with their new type checking infrastructure. Here's the supposedly offending code (no laughing or grimacing, please ;) char *s, *s1; s1 = strcpy((char ){ },s); and GCC 4.01's error messages
7
1930
by: Eric Laberge | last post by:
Aloha! This question is meant to be about C99 and unnamed compound objects. As I read, if such a construct as int *p = (int){0}; is used within a function, then it has "automatic storage duration associated with the enclosing block". So I tried the annexed code, and it compiles without a warning, and works as I expected.
8
3522
by: wespvp | last post by:
I am using PostgreSQL 7.4.1 on RedHat 7.2. The query I am executing is something like (I replaced all the return values with 'count'): db=> explain select count(*) from messages m join (select * from message_recipients r join addresses a on a.Address_Key=r.Recipient where a.Address='lra.edi@edi.cma-cgm.com') as foo on (m.Message_Key=foo.Message_Key AND (m.Message_Date >= '29-MAR-04') AND (m.Message_Date <= '31-MAR-04...
7
5448
by: Timo Haberkern | last post by:
Hi there, i have some troubles with my TSearch2 Installation. I have done this installation as described in http://www.sai.msu.su/~megera/oddmuse/index.cgi/Tsearch_V2_compound_words <http://www.sai.msu.su/%7Emegera/oddmuse/index.cgi/Tsearch_V2_compound_words> I used the german myspell dictionary from http://lingucomponent.openoffice.org/spell_dic.html and converted it with my2ispell
27
2553
by: SasQ | last post by:
Hello. I wonder if literal constants are objects, or they're only "naked" values not contained in any object? I have read that literal constants may not to be allocated by the compiler. If the Standard is saying that "object is a region of storage", I deduce from that that literal constants aren't objects because they may not be alocated as regions of storage in the memory.
27
2513
by: Nate Eldredge | last post by:
Consider the following pseudo-code: #include <opaque.h> struct foo { int a; opaque_t op; int b; };
0
8476
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8820
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8670
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7433
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6223
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5695
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4406
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2051
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1809
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.