Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Making sure an enum fits into an unsigned char

Reply
Thread Tools

Making sure an enum fits into an unsigned char

 
 
Alexander Farber
Guest
Posts: n/a
 
      08-12-2005
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.

 
Reply With Quote
 
 
 
 
SM Ryan
Guest
Posts: n/a
 
      08-12-2005
# 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.
 
Reply With Quote
 
 
 
 
Suman
Guest
Posts: n/a
 
      08-12-2005

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

 
Reply With Quote
 
Anton Petrusevich
Guest
Posts: n/a
 
      08-12-2005
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
 
Reply With Quote
 
Alexander Farber
Guest
Posts: n/a
 
      08-12-2005
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

 
Reply With Quote
 
Alexander Farber
Guest
Posts: n/a
 
      08-12-2005
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

 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      08-12-2005
SM Ryan <(E-Mail Removed)> 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
 
Reply With Quote
 
Anton Petrusevich
Guest
Posts: n/a
 
      08-12-2005
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
 
Reply With Quote
 
Alexander Farber
Guest
Posts: n/a
 
      08-12-2005
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

 
Reply With Quote
 
Suman
Guest
Posts: n/a
 
      08-12-2005

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


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Casting from const pair<const unsigned char*, size_t>* to constpair<unsigned char*, size_t>* Alex Vinokur C++ 9 10-13-2008 05:05 PM
Padding bits and char, unsigned char, signed char Ioannis Vranos C Programming 6 03-29-2008 10:55 AM
Padding bits and char, unsigned char, signed char Ioannis Vranos C++ 11 03-28-2008 10:47 PM
Linking error LNK2001 - "__declspec(dllimport) private: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Tidy(unsigned short)" (__imp_?_Tidy@?$basic_string@DU?$char_ sharmadeep1980@gmail.com C++ 1 07-07-2006 07:27 AM
void*, char*, unsigned char*, signed char* Steffen Fiksdal C Programming 1 05-09-2005 02:33 AM



Advertisments