typedef declares object / enum to int

Discussion in 'C Programming' started by Martin, Feb 23, 2005.

  1. Martin

    Martin Guest

    This post asks two questions, which I've illustrated in one C source file
    (see below), which clean compiles on my GNU compiler.

    1. In K&R2, Section A8.9 it says "Declarations whose storage class specifier
    is typedef do not declare object." When I compile and run my sample code,
    the value "2" is displayed. Clearly the typedef has created the enumerators
    S1, S2, and S3. This appears to contradict K&R2.

    2. The program below was created to emulate a Lint diagnostic I got in a
    much larger project. In that project, the equivalent line to fn(SYMBOL)
    gives the warning

    Converting enum '{...}' to int

    which I find puzzling. Enumerators are int anyway, whereas the enumeration
    has an integral value (according to K&R2, Section A4.4). A warning about an
    enumerator (int) being converted to an int seems meaningless; and a warning
    about the enumeration (integral type) being converted to int doesn't make
    sense because it's the enumerator S3 that gets
    passed to fn(). I've reproduced Lint's explanation of the warning below.

    /* typedef declaration; Lint warning */
    #include <stdio.h>

    typedef enum { S1, S2, S3 } an_enum_t;

    #define SYMBOL S3

    typedef unsigned int Word;
    void fn(Word w)
    {
    /* deliberately empty */
    }

    int main( void )
    {

    fn(SYMBOL);
    printf("%i\n", SYMBOL);
    return 0; /* success */
    }

    This is Lint's description of the warning:

    641 Converting enum to int -- An enumeration type was used in a context that
    required a computation such as an argument to an arithmetic operator or was
    compared with an integral argument. This warning will be suppressed if you
    use the integer model of enumeration (+fie) but you will lose some valuable
    type-checking in doing so. An intermediate policy is to simply turn off this
    warning. Assignment of int to enum will still be caught.

    This warning is not issued for a tagless enum without variables. For example

    enum {false,true};

    This cannot be used as a separate type. PC-lint/FlexeLint recognizes this
    and treats false and true as arithmetic constants.

    --
    Martin
     
    Martin, Feb 23, 2005
    #1
    1. Advertising

  2. Martin

    Ben Pfaff Guest

    "Martin" <martin.o_brien@[no-spam]which.net> writes:

    > 1. In K&R2, Section A8.9 it says "Declarations whose storage class specifier
    > is typedef do not declare object." When I compile and run my sample code,
    > the value "2" is displayed. Clearly the typedef has created the enumerators
    > S1, S2, and S3. This appears to contradict K&R2.


    Enumeration values are not objects. Objects are regions of
    storage, but enumeration values are just values.

    > 2. The program below was created to emulate a Lint diagnostic I got in a
    > much larger project. [...]


    I've never been impressed with lint diagnostics. Often they
    don't make a whole lot of sense in context, as you've discovered.
    --
    "The fact that there is a holy war doesn't mean that one of the sides
    doesn't suck - usually both do..."
    --Alexander Viro
     
    Ben Pfaff, Feb 23, 2005
    #2
    1. Advertising

  3. Martin

    Michael Mair Guest

    Martin wrote:
    > This post asks two questions, which I've illustrated in one C source file
    > (see below), which clean compiles on my GNU compiler.
    >
    > 1. In K&R2, Section A8.9 it says "Declarations whose storage class specifier
    > is typedef do not declare object." When I compile and run my sample code,
    > the value "2" is displayed. Clearly the typedef has created the enumerators
    > S1, S2, and S3. This appears to contradict K&R2.


    Enumeration constants are exactly that: Constants.
    They are not objects.

    > 2. The program below was created to emulate a Lint diagnostic I got in a
    > much larger project. In that project, the equivalent line to fn(SYMBOL)
    > gives the warning
    >
    > Converting enum '{...}' to int
    >
    > which I find puzzling. Enumerators are int anyway, whereas the enumeration
    > has an integral value (according to K&R2, Section A4.4). A warning about an
    > enumerator (int) being converted to an int seems meaningless; and a warning
    > about the enumeration (integral type) being converted to int doesn't make
    > sense because it's the enumerator S3 that gets
    > passed to fn(). I've reproduced Lint's explanation of the warning below.


    To clarify:
    Every enumerated type is distinct from every other enumerated or
    integer type but is compatible to either char or a signed or unsigned
    integer type. IOW: While the identifier S3 gives you a constant of type
    int, the underlying enumerated type is not necessarily int.


    Cheers
    Michael
    > /* typedef declaration; Lint warning */
    > #include <stdio.h>
    >
    > typedef enum { S1, S2, S3 } an_enum_t;
    >
    > #define SYMBOL S3
    >
    > typedef unsigned int Word;
    > void fn(Word w)
    > {
    > /* deliberately empty */
    > }
    >
    > int main( void )
    > {
    >
    > fn(SYMBOL);
    > printf("%i\n", SYMBOL);
    > return 0; /* success */
    > }
    >
    > This is Lint's description of the warning:
    >
    > 641 Converting enum to int -- An enumeration type was used in a context that
    > required a computation such as an argument to an arithmetic operator or was
    > compared with an integral argument. This warning will be suppressed if you
    > use the integer model of enumeration (+fie) but you will lose some valuable
    > type-checking in doing so. An intermediate policy is to simply turn off this
    > warning. Assignment of int to enum will still be caught.
    >
    > This warning is not issued for a tagless enum without variables. For example
    >
    > enum {false,true};
    >
    > This cannot be used as a separate type. PC-lint/FlexeLint recognizes this
    > and treats false and true as arithmetic constants.
    >



    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 23, 2005
    #3
  4. Off Topic: typedef declares object / enum to int

    Martin wrote:

    > This post asks two questions, which I've illustrated in one C source file
    > (see below), which clean compiles on my GNU compiler.
    >
    > 1. In K&R2, Section A8.9 it says "Declarations whose storage class specifier
    > is typedef do not declare object." When I compile and run my sample code,
    > the value "2" is displayed. Clearly the typedef has created the enumerators
    > S1, S2, and S3. This appears to contradict K&R2.


    No!
    S1, S2 and S3 are *values* that an object of type an_enum_t can have.
    They are *not* themselves objects.

    > 2. The program below was created to emulate a Lint diagnostic
    > [that] I got in a much larger project.
    > In that project, the equivalent line to fn(SYMBOL) gives the warning
    >
    > Converting enum '{...}' to int
    >
    > which I find puzzling. Enumerators are int anyway, whereas the enumeration
    > has an integral value (according to K&R2, Section A4.4). A warning about an
    > enumerator (int) being converted to an int seems meaningless;
    > and a warning about the enumeration (integral type) being converted to int
    > doesn't make sense because it's the enumerator S3 that gets passed to fn().
    > I've reproduced Lint's explanation of the warning below.


    > cat main.c

    // typedef declaration; Lint warning
    #include <stdio.h>

    typedef enum { S1, S2, S3 } an_enum_t;

    #define SYMBOL S3

    typedef unsigned int Word;

    void fn(Word w) {
    // deliberately empty
    }

    int main(int argc, char* argv[]) {
    fn(SYMBOL);
    printf("%i\n", SYMBOL);
    return 0; // success
    }

    > gcc -Wall -std=c99 -pedantic -o main main.c
    > ./main

    2


    > This is Lint's description of the warning:
    >
    > 641 Converting enum to int -- An enumeration type was used in a context that
    > required a computation such as an argument to an arithmetic operator or was
    > compared with an integral argument. This warning will be suppressed if you
    > use the integer model of enumeration (+fie) but you will lose some valuable
    > type-checking in doing so. An intermediate policy is to simply turn off this
    > warning. Assignment of int to enum will still be caught.
    >
    > This warning is not issued for a tagless enum without variables. For example
    >
    > enum {false,true};
    >
    > This cannot be used as a separate type. PC-lint/FlexeLint recognizes this
    > and treats false and true as arithmetic constants.


    So your complaint is that lint is nitpicking?
     
    E. Robert Tisdale, Feb 23, 2005
    #4
  5. Martin

    Martin Guest

    "Ben Pfaff" wrote:
    > Enumeration values are not objects. Objects are
    > regions of storage, but enumeration values are
    > just values.


    "just values"? I'm not sure I understand. Surely S1, S2, and S3 are
    identifiers representing integer constants.

    I think I'm surprised that the program even understands what S3 is and can
    print it out, because no variable of type an_enum_t has been declared.


    > I've never been impressed with lint diagnostics. Often they
    > don't make a whole lot of sense in context, as you've discovered.


    I do find it puzzling. I don't really understand what Lint sees as the
    problem.

    --
    Martin
     
    Martin, Feb 23, 2005
    #5
  6. Martin

    Martin Guest

    "Michael Mair" wrote:
    > To clarify:
    > Every enumerated type is distinct from every other enumerated or integer
    > type but is compatible to either char or a signed or unsigned integer
    > type. IOW: While the identifier S3 gives you a constant of type
    > int, the underlying enumerated type is not
    > necessarily int.


    But I'm passing the identifier S3 to function fn(), and S3 is the identifier
    of an integer constant. By all means warn me I'm passing an int to a
    function expecting unsigned int, but what does " Converting enum '{...}' to
    int" supposed to mean?

    --
    Martin
     
    Martin, Feb 23, 2005
    #6
  7. Martin

    Martin Guest

    Re: Off Topic: typedef declares object / enum to int

    "E. Robert Tisdale" wrote:
    > So your complaint is that lint is nitpicking?


    I'm not complaining. I'm seeking clarification.

    --
    Martin
     
    Martin, Feb 23, 2005
    #7
  8. Martin

    Ben Pfaff Guest

    "Martin" <martin.o_brien@[no-spam]which.net> writes:

    > "Ben Pfaff" wrote:
    >> Enumeration values are not objects. Objects are
    >> regions of storage, but enumeration values are
    >> just values.

    >
    > "just values"? I'm not sure I understand. Surely S1, S2, and S3 are
    > identifiers representing integer constants.


    S1, S2, and S3 are not associated with regions of storage. When
    you use one of them in your program, all you get is a value.
    --
    "When in doubt, treat ``feature'' as a pejorative.
    (Think of a hundred-bladed Swiss army knife.)"
    --Kernighan and Plauger, _Software Tools_
     
    Ben Pfaff, Feb 23, 2005
    #8
  9. Martin

    Michael Mair Guest

    Martin wrote:
    > "Michael Mair" wrote:
    >
    >>To clarify:
    >>Every enumerated type is distinct from every other enumerated or integer
    >>type but is compatible to either char or a signed or unsigned integer
    >>type. IOW: While the identifier S3 gives you a constant of type
    >>int, the underlying enumerated type is not
    >>necessarily int.

    >
    > But I'm passing the identifier S3 to function fn(), and S3 is the identifier
    > of an integer constant. By all means warn me I'm passing an int to a
    > function expecting unsigned int, but what does " Converting enum '{...}' to
    > int" supposed to mean?


    The thing is that *lint is sometimes too paranoid (even if your being
    paranoid does not mean they are not after you).
    This is such a case.

    It is not clear which type the enumerated type is compatible to,
    thus lint sees this as a potentially dangerous conversion -- without
    considering the fact that the semantics say this never can go wrong
    as all candidate types undergo the standard integer promotions.

    I would just throw this special warning away. Even if we forget for
    a moment that casting to shut the compiler or lint up is evil, it
    is completely pointless here. Casting a return value to void may
    make sense sometimes but casting a constant of type int to int does
    not.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 23, 2005
    #9
  10. Martin

    Alan Balmer Guest

    On Wed, 23 Feb 2005 23:18:45 -0000, "Martin"
    <martin.o_brien@[no-spam]which.net> wrote:

    >"Michael Mair" wrote:
    >> To clarify:
    >> Every enumerated type is distinct from every other enumerated or integer
    >> type but is compatible to either char or a signed or unsigned integer
    >> type. IOW: While the identifier S3 gives you a constant of type
    >> int, the underlying enumerated type is not
    >> necessarily int.

    >
    >But I'm passing the identifier S3 to function fn(), and S3 is the identifier
    >of an integer constant. By all means warn me I'm passing an int to a
    >function expecting unsigned int, but what does " Converting enum '{...}' to
    >int" supposed to mean?


    The enum value is not necessarily an int.

    6.7.2.2 par 4:
    Each enumerated type shall be compatible with char, a signed integer
    type, or an unsigned integer type. The choice of type is
    implementation-defined,108) but shall be capable of representing the
    values of all the members of the enumeration.

    --
    Al Balmer
    Balmer Consulting
     
    Alan Balmer, Feb 23, 2005
    #10
  11. Martin

    Michael Mair Guest

    Alan Balmer wrote:
    > On Wed, 23 Feb 2005 23:18:45 -0000, "Martin"
    > <martin.o_brien@[no-spam]which.net> wrote:
    >
    >
    >>"Michael Mair" wrote:
    >>
    >>>To clarify:
    >>>Every enumerated type is distinct from every other enumerated or integer
    >>>type but is compatible to either char or a signed or unsigned integer
    >>>type. IOW: While the identifier S3 gives you a constant of type
    >>>int, the underlying enumerated type is not
    >>>necessarily int.

    >>
    >>But I'm passing the identifier S3 to function fn(), and S3 is the identifier
    >>of an integer constant. By all means warn me I'm passing an int to a
    >>function expecting unsigned int, but what does " Converting enum '{...}' to
    >>int" supposed to mean?

    >
    >
    > The enum value is not necessarily an int.
    >
    > 6.7.2.2 par 4:
    > Each enumerated type shall be compatible with char, a signed integer
    > type, or an unsigned integer type. The choice of type is
    > implementation-defined,108) but shall be capable of representing the
    > values of all the members of the enumeration.


    However, par 3 states that the identifiers give us constants
    of type int.

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 23, 2005
    #11
  12. Martin wrote:

    > "Ben Pfaff" wrote:
    >> Enumeration values are not objects. Objects are
    >> regions of storage, but enumeration values are
    >> just values.

    >
    > "just values"? I'm not sure I understand. Surely S1, S2, and S3 are
    > identifiers representing integer constants.


    In that case, why don't you try to assign a new value to them?


    Christian
     
    Christian Kandeler, Feb 24, 2005
    #12
  13. On Wed, 23 Feb 2005 23:18:45 -0000, Martin
    <martin.o_brien@[> wrote:

    > "Michael Mair" wrote:
    >> To clarify:
    >> Every enumerated type is distinct from every other enumerated or integer
    >> type but is compatible to either char or a signed or unsigned integer
    >> type. IOW: While the identifier S3 gives you a constant of type
    >> int, the underlying enumerated type is not
    >> necessarily int.

    >
    > But I'm passing the identifier S3 to function fn(), and S3 is the identifier
    > of an integer constant. By all means warn me I'm passing an int to a
    > function expecting unsigned int, but what does " Converting enum '{...}' to
    > int" supposed to mean?


    It means that the compiler is being way over-zealous in issuing warning
    (at least one of the ARM compilers is like that). Or possibly it means
    that you are compiling C using a C++ compiler, where enums are a
    different type from int.

    I don't want warnings when converting int to unsigned int either, since
    that is explicitly defined in the standard -- and would mean that saying
    unsigned int fred = 1; gave a warning! It's bad enough when compilers
    warn every time I convert with potential loss of precision or range
    (like assigning an int to to a char), it results in loads of unnecessary
    casts just to shut the compiler up.

    Chris C
     
    Chris Croughton, Feb 24, 2005
    #13
  14. Martin

    Richard Bos Guest

    "Martin" <martin.o_brien@[no-spam]which.net> wrote:

    > "Ben Pfaff" wrote:
    > > Enumeration values are not objects. Objects are
    > > regions of storage, but enumeration values are
    > > just values.

    >
    > "just values"? I'm not sure I understand. Surely S1, S2, and S3 are
    > identifiers representing integer constants.


    Integer constant _values_, yes. Not integer objects. In effect, once
    you've defined that enum, S1, S2 and S3 have the same status as 3, 4.5,
    or 'a'.

    > I think I'm surprised that the program even understands what S3 is and can
    > print it out, because no variable of type an_enum_t has been declared.


    So? Even if I have declared no variables of type char, putchar('x') will
    work. S3 has a _value_. Once you've defined an an_enum_t object, you can
    give that the value of S1, S2, or S3; but no matter which value the
    object has, the program still recognises all those values. How else
    would you initialise an an_enum_t in the first place, if you need one to
    _have_ a value to be able to use that value?

    > > I've never been impressed with lint diagnostics. Often they
    > > don't make a whole lot of sense in context, as you've discovered.

    >
    > I do find it puzzling. I don't really understand what Lint sees as the
    > problem.


    In all probability neither does lint.

    Richard
     
    Richard Bos, Feb 24, 2005
    #14
    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. Thomas Marti
    Replies:
    1
    Views:
    1,172
    Jesper Zedlitz
    Nov 25, 2003
  2. Schnoffos
    Replies:
    2
    Views:
    1,220
    Martien Verbruggen
    Jun 27, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,646
    Old Wolf
    Jan 20, 2004
  4. jacob navia

    is "typedef int int;" illegal????

    jacob navia, Mar 24, 2006, in forum: C Programming
    Replies:
    134
    Views:
    2,552
    Douglas A. Gwyn
    Apr 5, 2006
  5. Replies:
    1
    Views:
    332
    Victor Bazarov
    Feb 23, 2006
Loading...

Share This Page