Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Making sure an enum fits into an unsigned char (http://www.velocityreviews.com/forums/t439060-making-sure-an-enum-fits-into-an-unsigned-char.html)

Alexander Farber 08-12-2005 08:04 AM

Making sure an enum fits into an unsigned char
 
Hi,

I have a UNIX-server written in C, which exchanges messages
with Java clients. In the message the 1 byte is its length,
the 2nd a player number and the 3rd byte is an event id:

/* 0. byte: Total message length in bytes (inlcuding this byte) */
/* 1. byte: Player number (0, 1 or 2) */
/* 2. byte: Event id (10 - 22) */
/* 3.-255.: Argument (252 bytes or 126 big-endian UTF-16 chars) */

typedef unsigned char byte;

typedef struct {
byte len,
num,
id,
arg[MAXARG];
} msg;

For the event ids I currently use #defines:

#define PREF_NAME 10
#define PREF_PASS 11
#define PREF_CHAT 12
#define PREF_CARD 13

But I would actually prefer to use enums instead, something like:

enum event_id {
PREF_NAME = 10,
PREF_PASS,
PREF_CHAT,
PREF_CARD
}

However enums are integers, aren't they? Could
I somehow specify that my enums are 8 bit long only?

One more question: how do you use typedef's with enum's?
I've tried to change this code:

enum direction {
FROM,
TO
};

void print_node(unsigned i, unsigned j, enum direction dir, const node
*np);

To the following, but get strange unrelated error messages
(I suspect that I declare a variable "direction" there instead):

typedef enum {
FROM,
TO
} direction;

void print_node(unsigned i, unsigned j, direction dir, const node *np);

Thank you
Alex

PS: I'm using gcc 3.3.5 on OpenBSD 3.7.


SM Ryan 08-12-2005 08:18 AM

Re: Making sure an enum fits into an unsigned char
 
# enum event_id {
# PREF_NAME = 10,
# PREF_PASS,
# PREF_CHAT,
# PREF_CARD
# }
#
# However enums are integers, aren't they? Could
# I somehow specify that my enums are 8 bit long only?

Use byte instead of enum event_id.

byte variable = PREF_NAME;

This is allowed and assuming PREF_NAME is in the range of values
byte can hold, there will be no loss of value.


# One more question: how do you use typedef's with enum's?
# I've tried to change this code:
#
# enum direction {
# FROM,
# TO
# };
#
# void print_node(unsigned i, unsigned j, enum direction dir, const node
# *np);
#
# To the following, but get strange unrelated error messages
# (I suspect that I declare a variable "direction" there instead):
#
# typedef enum {
# FROM,
# TO
# } direction;

If you want to better control over the allocation of direction
objects, you can use
typedef byte direction;
instead.

Without seeing the error message, it's hard to guess. Does the typedef
proceed any reference to the type name.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
You hate people.
But I love gatherings. Isn't it ironic.

Suman 08-12-2005 08:28 AM

Re: Making sure an enum fits into an unsigned char
 

Alexander Farber wrote:
> Hi,
>
> I have a UNIX-server written in C, which exchanges messages
> with Java clients. In the message the 1 byte is its length,
> the 2nd a player number and the 3rd byte is an event id:
>
> /* 0. byte: Total message length in bytes (inlcuding this byte) */
> /* 1. byte: Player number (0, 1 or 2) */
> /* 2. byte: Event id (10 - 22) */
> /* 3.-255.: Argument (252 bytes or 126 big-endian UTF-16 chars) */
>
> typedef unsigned char byte;
>
> typedef struct {
> byte len,
> num,
> id,
> arg[MAXARG];
> } msg;
>
> For the event ids I currently use #defines:
>
> #define PREF_NAME 10
> #define PREF_PASS 11
> #define PREF_CHAT 12
> #define PREF_CARD 13
>
> But I would actually prefer to use enums instead, something like:
>
> enum event_id {
> PREF_NAME = 10,
> PREF_PASS,
> PREF_CHAT,
> PREF_CARD
> }
>
> However enums are integers, aren't they?


Quotes from the C99 draft that might help you:

Enum:
Constraints:
....
"The identifiers in an enumerator list are
declared as constants that have type int and
may appear wherever such are permitted..."

and a footnote:
"An implementation may delay the choice of which
integer type until all enumeration constants have
been seen."

>Could
> I somehow specify that my enums are 8 bit long only?


Why would you want that?

> One more question: how do you use typedef's with enum's?
> I've tried to change this code:
>
> enum direction {


typedef enum direction {
> FROM,
> TO
> };


} direction;
should work.

>
> void print_node(unsigned i, unsigned j, enum direction dir, const node
> *np);
>
> To the following, but get strange unrelated error messages
> (I suspect that I declare a variable "direction" there instead):
>


Possible, use your text editor's search option to the hilt ;-)
But enums have their own namespace, and even the following:

typedef enum _myBool { FALSEY, TRUEY } _myBool;
void demo( _myBool f )
{
int _myBool;
/* following are to get rid of unused variable warning */
f = !f;
_myBool = 1;
}

int main()
{
}

compiles (with gcc -std=c99 -W -Wall -pedantic) without any warnings.
Had you posted the error message(s), it would have been handy.

> typedef enum {
> FROM,
> TO
> } direction;


Should work as well!
> void print_node(unsigned i, unsigned j, direction dir, const node *np);
>
> Thank you
> Alex
>
> PS: I'm using gcc 3.3.5 on OpenBSD 3.7.

HTH


Anton Petrusevich 08-12-2005 08:30 AM

Re: Making sure an enum fits into an unsigned char
 
Alexander Farber wrote:

> I have a UNIX-server written in C, which exchanges messages
> with Java clients. In the message the 1 byte is its length,
> the 2nd a player number and the 3rd byte is an event id:
> /* 0. byte: Total message length in bytes (inlcuding this byte) */
> /* 1. byte: Player number (0, 1 or 2) */
> /* 2. byte: Event id (10 - 22) */
> /* 3.-255.: Argument (252 bytes or 126 big-endian UTF-16 chars) */
> typedef unsigned char byte;
> typedef struct {
> byte len,
> num,
> id,
> arg[MAXARG];
> } msg;


How do you know that there's no padding between fields? I would suggest to
think about it.
--
Anton Petrusevich

Alexander Farber 08-12-2005 09:02 AM

Re: Making sure an enum fits into an unsigned char
 
Hi,

> How do you know that there's no padding between fields?
> I would suggest to think about it.


I dunno, it seems to work ok on Linux and OpenBSD:

/* 0. byte: Total message length in bytes (inlcuding this byte) */
/* 1. byte: Player number (0, 1 or 2) */
/* 2. byte: Event id (10 - 22) */
/* 3.-255.: Argument (252 bytes or 126 big-endian UTF-16 chars) */

typedef unsigned char byte;

typedef struct {
byte len,
num,
id,
arg[MAXARG];
} msg;

/* an element of a singly-linked list or queue */
typedef struct node_s {
struct node_s *next;
#ifndef NDEBUG
/* used to track (de)allocated nodes */
unsigned memid;
#endif
union {
msg m;
byte buf[MAXBUF];
} node_u;
#define node_len node_u.m.len
#define node_num node_u.m.num
#define node_id node_u.m.id
#define node_arg node_u.m.arg
#define node_buf node_u.buf
} node;

And then I read() and writev() those messages (after a poll()):

/* on the 1st time try to read 3 bytes (i.e. no more */
/* than the min. message length) to find out the length */

if (0 == cp->nfrom)
n = read(cp->fd, np->node_buf, 3);
else
n = read(cp->fd, &(np->node_buf[cp->nfrom]),
np->node_len - cp->nfrom);
.........

iov[0].iov_base = np->node_buf + cp->nto;
iov[0].iov_len = np->node_len - cp->nto;

for (k = 1, np = np->next; np && k < IOV_MAX; k++, np = np->next) {
iov[k].iov_base = np->node_buf;
iov[k].iov_len = np->node_len;
}
n = writev(cp->fd, iov, k);
........

I.e. I refer to the node_u.buf member in my read()/writev() calls.

Do you have a better suggestion please?

Regards
Alex


Alexander Farber 08-12-2005 09:06 AM

Re: Making sure an enum fits into an unsigned char
 
Hi Suman,

>>Could I somehow specify that my enums are 8 bit long only?


> Why would you want that?


I need that because my messages should be at most 255 bytes long, with
the 1st byte containing the message length.

That way I can poll(), then read the 1st byte (ok the first 3 bytes)
without blocking and then poll() again and read the rest.

I have a non-forking iterative server and must be sure that no client
I/O will block or my server will hang for everyone

Regards
Alex


Richard Bos 08-12-2005 09:24 AM

Re: Making sure an enum fits into an unsigned char
 
SM Ryan <wyrmwif@tango-sierra-oscar-foxtrot-tango.fake.org> wrote:

> # enum event_id {
> # PREF_NAME = 10,
> # PREF_PASS,
> # PREF_CHAT,
> # PREF_CARD
> # }
> #
> # However enums are integers, aren't they? Could
> # I somehow specify that my enums are 8 bit long only?
>
> Use byte instead of enum event_id.
>
> byte variable = PREF_NAME;


There is no such thing in C.

Richard

Anton Petrusevich 08-12-2005 10:04 AM

Re: Making sure an enum fits into an unsigned char
 
Alexander Farber wrote:

>> How do you know that there's no padding between fields?
>> I would suggest to think about it.

> I dunno, it seems to work ok on Linux and OpenBSD:


I would say: it accidentally works. You are really streaming dumps of
memory. I would think about host<->network translation routines without any
padding assumptions of structure members.
--
Anton Petrusevich

Alexander Farber 08-12-2005 10:10 AM

Re: Making sure an enum fits into an unsigned char
 
Thanks, but I have just looked around and I think I'll better
just use a gcc packed __attribute__ (also for my enum):
http://gcc.gnu.org/onlinedocs/gcc-3....ttributes.html


Suman 08-12-2005 10:17 AM

Re: Making sure an enum fits into an unsigned char
 

Alexander Farber wrote:
> Hi Suman,
>
> >>Could I somehow specify that my enums are 8 bit long only?

>
> > Why would you want that?

>
> I need that because my messages should be at most 255 bytes long, with
> the 1st byte containing the message length.
>
> That way I can poll(), then read the 1st byte (ok the first 3 bytes)
> without blocking and then poll() again and read the rest.


Actually, I should have formulated my query differently. Should have
been:
Is it that you want your enums to be exactly 8 bits?
If it is yes, I think you need to use bit-fields, not enums.
Manipulating them might be a pain, but that's the way it is.

OTOH, if it is not, the quoted footnote in my earlier post
should be of some help.

And finally, I am sure you know this, but still, a byte
as typedef-ed by you has CHAR_BIT number of bits,
and that the value of CHAR_BIT is often but not necessarily 8.
> I have a non-forking iterative server and must be sure that no client
> I/O will block or my server will hang for everyone
>
> Regards
> Alex




All times are GMT. The time now is 04:26 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.