Making sure an enum fits into an unsigned char

Discussion in 'C Programming' started by Alexander Farber, Aug 12, 2005.

  1. 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.
     
    Alexander Farber, Aug 12, 2005
    #1
    1. Advertising

  2. Alexander Farber

    SM Ryan Guest

    # 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.
     
    SM Ryan, Aug 12, 2005
    #2
    1. Advertising

  3. Alexander Farber

    Suman Guest

    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
     
    Suman, Aug 12, 2005
    #3
  4. 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
     
    Anton Petrusevich, Aug 12, 2005
    #4
  5. 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, Aug 12, 2005
    #5
  6. 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
     
    Alexander Farber, Aug 12, 2005
    #6
  7. Alexander Farber

    Richard Bos Guest

    SM Ryan <> 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
     
    Richard Bos, Aug 12, 2005
    #7
  8. 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
     
    Anton Petrusevich, Aug 12, 2005
    #8
  9. Alexander Farber, Aug 12, 2005
    #9
  10. Alexander Farber

    Suman Guest

    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
     
    Suman, Aug 12, 2005
    #10
  11. Alexander Farber

    SM Ryan Guest

    (Richard Bos) wrote:
    # SM Ryan <> 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.

    The original poster included a typedef for byte. Some of us don't
    need to quote an entire post to remember what was there.

    Insert apology in space provided.
    [___________________________________________________]
    [___________________________________________________]
    [___________________________________________________]
    [___________________________________________________]

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    No pleasure, no rapture, no exquisite sin greater than central air.
     
    SM Ryan, Aug 12, 2005
    #11
  12. Alexander Farber

    Flash Gordon Guest

    SM Ryan wrote:
    > (Richard Bos) wrote:
    > # SM Ryan <> wrote:


    <snip>

    > # > byte variable = PREF_NAME;
    > #
    > # There is no such thing in C.
    >
    > The original poster included a typedef for byte. Some of us don't
    > need to quote an entire post to remember what was there.
    >
    > Insert apology in space provided.


    However, as you well know (or should do by now), other people might not
    have received that message and you can't remember something you haven't
    seen.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Aug 13, 2005
    #12
  13. Alexander Farber

    SM Ryan Guest

    Flash Gordon <> wrote:
    # SM Ryan wrote:
    # > (Richard Bos) wrote:
    # > # SM Ryan <> wrote:
    #
    # <snip>
    #
    # > # > byte variable = PREF_NAME;
    # > #
    # > # There is no such thing in C.
    # >
    # > The original poster included a typedef for byte. Some of us don't
    # > need to quote an entire post to remember what was there.
    # >
    # > Insert apology in space provided.
    #
    # However, as you well know (or should do by now), other people might not
    # have received that message and you can't remember something you haven't
    # seen.

    When in a hole, stop digging

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    God's a skeeball fanatic.
     
    SM Ryan, Aug 13, 2005
    #13
  14. Alexander Farber

    Flash Gordon Guest

    SM Ryan wrote:
    > Flash Gordon <> wrote:
    > # SM Ryan wrote:
    > # > (Richard Bos) wrote:
    > # > # SM Ryan <> wrote:
    > #
    > # <snip>
    > #
    > # > # > byte variable = PREF_NAME;
    > # > #
    > # > # There is no such thing in C.
    > # >
    > # > The original poster included a typedef for byte. Some of us don't
    > # > need to quote an entire post to remember what was there.
    > # >
    > # > Insert apology in space provided.
    > #
    > # However, as you well know (or should do by now), other people might not
    > # have received that message and you can't remember something you haven't
    > # seen.
    >
    > When in a hole, stop digging


    If I ever find myself in a hole I'll remember that. However, I'm not in
    one and don't thing Richard Bos is either. I stand by what I said and
    see nothing wrong with Richard's comment based on the context provided.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Aug 13, 2005
    #14
  15. Alexander Farber

    CBFalconer Guest

    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;
    >
    > 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?


    You should have no difficulty as long as the enum values are within
    the range of an unsigned char. Just substitude the enum definition
    for the #defines. I have also used them for bit mapped errors by
    something like:

    typedef enum errcode = {NO_ERR,
    ERR_1b,
    ERR_2b,
    ERR_4b = 4,
    ERR_8b = 8} errcode;

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Aug 14, 2005
    #15
  16. Alexander Farber

    Richard Bos Guest

    SM Ryan <> wrote:

    > (Richard Bos) wrote:
    > # SM Ryan <> 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.
    >
    > The original poster included a typedef for byte.


    Then you should've quoted that.

    > Some of us don't need to quote an entire post to remember what was there.


    Some of us understand better than that how Usenet works.

    Richard
     
    Richard Bos, Aug 15, 2005
    #16
  17. Alexander Farber

    SM Ryan Guest

    (Richard Bos) wrote:

    # Some of us understand better than that how Usenet works.

    Then try this

    telnet post.news.xs4all.nl 119
    article <>
    quit

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    I'm not even supposed to be here today.
     
    SM Ryan, Aug 15, 2005
    #17
  18. Alexander Farber

    CBFalconer Guest

    Richard Bos wrote:
    > SM Ryan <> wrote:
    > > (Richard Bos) wrote:
    > > # SM Ryan <> 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.
    > >
    > > The original poster included a typedef for byte.

    >
    > Then you should've quoted that.
    >
    > > Some of us don't need to quote an entire post to remember what was there.

    >
    > Some of us understand better than that how Usenet works.


    In fact some of us are even capable of using normal quote markers.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Aug 15, 2005
    #18
  19. SM Ryan <> writes:
    > (Richard Bos) wrote:
    >
    > # Some of us understand better than that how Usenet works.
    >
    > Then try this
    >
    > telnet post.news.xs4all.nl 119
    > article <>
    > quit


    % telnet post.news.xs4all.nl 119
    Trying 194.109.133.8...

    It hangs indefinitely. I don't think post.news.xs4all.nl wants to
    talk to me.

    And I'll take this opportunity to ask, one more time, why you insist
    on using your non-traditional '#' quote character. You know it causes
    problems for some readers. You know that it would be trivial for you
    to use '>', as almost everyone else does, and that doing so would
    immediately cause you to be taken more seriously. And I know that I'm
    wasting my time asking this again.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 15, 2005
    #19
  20. Alexander Farber

    SM Ryan Guest

    Alternative nomination for Bartlo PAP was Re: Making sure an enum fits into an unsigned char

    Keith Thompson <> wrote:

    YACLCNKWB.

    Yet another comp.lang.c netkop wannabe.


    # SM Ryan <> writes:
    # > (Richard Bos) wrote:
    # >
    # > # Some of us understand better than that how Usenet works.
    # >
    # > Then try this
    # >
    # > telnet post.news.xs4all.nl 119
    # > article <>
    # > quit
    #
    # % telnet post.news.xs4all.nl 119
    # Trying 194.109.133.8...
    #
    # It hangs indefinitely. I don't think post.news.xs4all.nl wants to
    # talk to me.
    #
    # And I'll take this opportunity to ask, one more time, why you insist
    # on using your non-traditional '#' quote character. You know it causes
    # problems for some readers. You know that it would be trivial for you
    # to use '>', as almost everyone else does, and that doing so would
    # immediately cause you to be taken more seriously. And I know that I'm
    # wasting my time asking this again.
    #
    # --
    # Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    # San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    # We must do something. This is something. Therefore, we must do this.
    #
    #

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    If your job was as meaningless as theirs, wouldn't you go crazy too?
     
    SM Ryan, Aug 16, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steffen Fiksdal

    void*, char*, unsigned char*, signed char*

    Steffen Fiksdal, May 8, 2005, in forum: C Programming
    Replies:
    1
    Views:
    588
    Jack Klein
    May 9, 2005
  2. Ioannis Vranos
    Replies:
    11
    Views:
    762
    Ioannis Vranos
    Mar 28, 2008
  3. Ioannis Vranos

    Padding bits and char, unsigned char, signed char

    Ioannis Vranos, Mar 28, 2008, in forum: C Programming
    Replies:
    6
    Views:
    614
    Ben Bacarisse
    Mar 29, 2008
  4. Alex Vinokur
    Replies:
    9
    Views:
    798
    James Kanze
    Oct 13, 2008
  5. pozz
    Replies:
    12
    Views:
    744
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page