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. 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.
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/
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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
|
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.
|
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:
|
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
|
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.
| |
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...
|
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
|
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.
|
by: Nate Eldredge |
last post by:
Consider the following pseudo-code:
#include <opaque.h>
struct foo {
int a;
opaque_t op;
int b;
};
|
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...
|
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...
| |
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...
|
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...
|
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...
|
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();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
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...
| |