Weird warning about data type range

Discussion in 'C++' started by Digital Puer, Aug 29, 2009.

  1. Digital Puer

    Digital Puer Guest

    I am seeing this very weird warning about
    data type range. I am using g++ 4.1.2 (but this
    applies to gcc as well).

    I have this program:

    #include <cstdio>
    main()
    {
    char c = 27;

    if (c >= 110 &&
    c <= 127)
    {
    printf("hi");
    }
    }


    When I compile it with g++, I get the warning:
    test_range.cpp:7: warning: comparison is always true due to limited
    range of data type

    Line 7 is the comparison "c <= 127". Ok fine, that will always
    be true, but the entire if-expression may not be true since
    there is && in the expression.

    Can someone tell me how to shut off this warning?
    Digital Puer, Aug 29, 2009
    #1
    1. Advertising

  2. Digital Puer wrote:
    > I am seeing this very weird warning about
    > data type range. I am using g++ 4.1.2 (but this
    > applies to gcc as well).
    >
    > I have this program:
    >
    > #include <cstdio>
    > main()
    > {
    > char c = 27;
    >
    > if (c >= 110 &&
    > c <= 127)
    > {
    > printf("hi");
    > }
    > }
    >
    >
    > When I compile it with g++, I get the warning:
    > test_range.cpp:7: warning: comparison is always true due to limited
    > range of data type
    >
    > Line 7 is the comparison "c <= 127". Ok fine, that will always
    > be true, but the entire if-expression may not be true since
    > there is && in the expression.


    It's not saying that the expression is always true. It's saying that
    that comparison is always true and thus a nop.
    Juha Nieminen, Aug 29, 2009
    #2
    1. Advertising

  3. Digital Puer

    SG Guest

    On 29 Aug., 13:20, Stuart Golodetz <> wrote:
    >
    > Note it doesn't say anything about the entire if condition, just about a
    > particular comparison (specifically the c <= 127 one). It would seem
    > that char is signed by default on your platform. To get rid of the
    > warning, just delete the second comparison, i.e. change to using:
    >
    > if(c >= 110)


    That's not really satisfactory if you want your code to be portable
    and support CHAR_MAX>127 cases. I'm not really interested in whether
    the compiler figured out that it can ignore the c<=127 test because
    the standard doesn't guarantee CHAR_MAX to be 127. CHAR_MAX can be
    larger.

    I do appreciate warnings, though. A warning in cases like

    unsigned foo = getfoo();
    if (foo>=0) {
    // ...
    }

    is totally fine because foo can never be negative regardless of the
    implementation details.

    Cheers!
    SG
    SG, Aug 29, 2009
    #3
  4. Digital Puer

    Jonathan Lee Guest

    On Aug 29, 3:33 am, Digital Puer <> wrote:
    > Line 7 is the comparison "c <= 127". Ok fine, that will always
    > be true, but the entire if-expression may not be true since
    > there is && in the expression.


    Why not just #include <climits> and wrap the second half in an #if?

    if (c >= 110
    #if (CHAR_MAX > 127)
    && c <= 127
    #endif
    ) {
    ...
    }

    I know its not pretty but either the test stays (and the compiler
    produces the warning), or the test is somehow removed.

    --Jonathan
    Jonathan Lee, Aug 29, 2009
    #4
  5. Digital Puer

    Digital Puer Guest

    Thanks for everyone's help.

    What I am really trying to do is to test if
    characters in a std::string are alphanumeric
    characters in the Latin-1 encoding. I have
    the following:


    #define IS_ALPHANUMERIC(x) ( \
    ((x) >= 48 && (x) <= 57 ) || \
    ((x) >= 65 && (x) <= 90 ) || \
    ((x) >= 97 && (x) <= 122) || \
    ((x) >= 192 && (x) <= 214) || \
    ((x) >= 216 && (x) <= 246) || \
    ((x) >= 248 && (x) <= 255) )

    string s = getLatin1Text();
    int len = s.size();
    for (int i = 0; i < len; i++)
    {
    if (! IS_ALPHANUMERIC(s.at(i)))
    {
    ...
    }
    }

    When I compile that, the last check (x <= 255)
    gives the same warning that I showed in my
    original post:

    warning: comparison is always true due to limited range of data type

    I guess I will have to isolate away the last check
    with a #IF statement.
    Digital Puer, Aug 30, 2009
    #5
  6. Digital Puer wrote:
    > #define IS_ALPHANUMERIC(x) ( \
    > ((x) >= 48 && (x) <= 57 ) || \
    > ((x) >= 65 && (x) <= 90 ) || \
    > ((x) >= 97 && (x) <= 122) || \
    > ((x) >= 192 && (x) <= 214) || \
    > ((x) >= 216 && (x) <= 246) || \
    > ((x) >= 248 && (x) <= 255) )
    >
    > string s = getLatin1Text();
    > int len = s.size();
    > for (int i = 0; i < len; i++)
    > {
    > if (! IS_ALPHANUMERIC(s.at(i)))
    > {
    > ...
    > }
    > }


    I don't think that's doing what you want it to do.

    A std::string contains chars, which are usually signed in most
    systems. Values outside the ASCII range will thus have *negative*
    values. When you do eg. a "x >= 248" what will happen is that x, which
    is a signed char, will first be promoted to an int, and then compared to
    248. Since 248 is larger than 127, the comparison will always yield false.

    And btw, this is a great example where using a preprocessor macro
    instead of an inline function is a *bad* idea. With the macro you will
    be silently calling "s.at(i)" 12 times per call, rather than just once.
    (Might not be so relevant if it was "s", but with "s.at(i)" 11 of the
    boundary checks will be completely useless.)

    What you need is an inline function which takes a char as parameter,
    then internally casts it to unsigned char, and then compares it to
    unsigned char literals.
    Juha Nieminen, Aug 30, 2009
    #6
  7. Digital Puer

    Jonathan Lee Guest

    On Aug 29, 8:35 pm, Digital Puer <> wrote:
    > What I am really trying to do is to test if
    > characters in a std::string are alphanumeric
    > characters in the Latin-1 encoding. I have
    > the following:


    I think <locale> offers isalnum() to do just that. I haven't used it
    before, but the way I understand it you can create the appropriate
    locale and then the library does it for you. Ex.,

    #include <locale>
    #include <string.

    // Not sure on the constructor argument here...
    std::locale latin1("en_US.ISO8859-1");
    std::string s;

    ...

    for (size_t i = 0; i < s.length(); ++i) {
    if (std::isalnum(s, latin1)) { ... }
    }

    Anyone know more?

    --Jonathan
    Jonathan Lee, Aug 30, 2009
    #7
  8. Digital Puer

    Jerry Coffin Guest

    In article <ad7ec9cc-6e85-4d12-8ebf-6072d20e2617
    @z4g2000prh.googlegroups.com>, says...
    >
    > Thanks for everyone's help.
    >
    > What I am really trying to do is to test if
    > characters in a std::string are alphanumeric
    > characters in the Latin-1 encoding. I have
    > the following:
    >
    >
    > #define IS_ALPHANUMERIC(x) ( \
    > ((x) >= 48 && (x) <= 57 ) || \
    > ((x) >= 65 && (x) <= 90 ) || \
    > ((x) >= 97 && (x) <= 122) || \
    > ((x) >= 192 && (x) <= 214) || \
    > ((x) >= 216 && (x) <= 246) || \
    > ((x) >= 248 && (x) <= 255) )
    >
    > string s = getLatin1Text();
    > int len = s.size();
    > for (int i = 0; i < len; i++)
    > {
    > if (! IS_ALPHANUMERIC(s.at(i)))
    > {
    > ...
    > }
    > }


    If I had to do this, I think I'd use something like this:

    #include <climits>
    #include <vector>
    #include <algorithm>

    struct alphanumeric_table {
    std::vector<bool> table;
    public:
    #define elements(r) (sizeof(r)/sizeof(r[0]))

    alphanumeric_table() : table(UCHAR_MAX+2, false) {
    static const int ranges[] = {
    48, 57,
    65, 90,
    97, 122,
    192, 214,
    216, 246,
    248, 255
    };


    for (int i=0; i<elements(ranges); i+=2)
    std::fill(table.begin()+ranges+1,
    table.begin()+ranges[i+1]+2,
    true);
    }

    bool operator[](int n) { return table[unsigned char(n+1)]; }
    } alpha_table;

    inline bool is_alphanumeric(int n) {
    return alpha_table[n];
    }

    This assumes that EOF is -1. Technically this isn't required (any
    negative value is allowed) but it's extremely common -- to the point
    that I'm not sure I've ever seen or heard of it actually having any
    other value. In any case, the reason for the "+1"in most places is to
    get a range from 0 through the maximum, so we can use it directly as
    an index into the vector.

    --
    Later,
    Jerry.
    Jerry Coffin, Aug 30, 2009
    #8
  9. Digital Puer

    Digital Puer Guest

    On Aug 30, 11:27 am, Jerry Coffin <> wrote:
    > In article <ad7ec9cc-6e85-4d12-8ebf-6072d20e2617
    > @z4g2000prh.googlegroups.com>, says...
    >
    >
    >
    >
    >
    >
    >
    > > Thanks for everyone's help.

    >
    > > What I am really trying to do is to test if
    > > characters in a std::string are alphanumeric
    > > characters in the Latin-1 encoding. I have
    > > the following:

    >
    > > #define IS_ALPHANUMERIC(x) ( \
    > >     ((x) >= 48  && (x) <= 57 ) || \
    > >     ((x) >= 65  && (x) <= 90 ) || \
    > >     ((x) >= 97  && (x) <= 122) || \
    > >     ((x) >= 192 && (x) <= 214) || \
    > >     ((x) >= 216 && (x) <= 246) || \
    > >     ((x) >= 248 && (x) <= 255) )

    >
    > > string s = getLatin1Text();
    > > int len = s.size();
    > > for (int i = 0; i < len; i++)
    > > {
    > >   if (! IS_ALPHANUMERIC(s.at(i)))
    > >   {
    > >      ...
    > >   }
    > > }

    >
    > If I had to do this, I think I'd use something like this:
    >
    > #include <climits>
    > #include <vector>
    > #include <algorithm>
    >
    > struct alphanumeric_table {
    >         std::vector<bool> table;
    > public:    
    > #define elements(r) (sizeof(r)/sizeof(r[0]))
    >
    >         alphanumeric_table() : table(UCHAR_MAX+2, false) {
    >                 static const int ranges[] = {
    >                         48, 57,
    >                         65, 90,
    >                         97, 122,
    >                         192, 214,
    >                         216, 246,
    >                         248, 255
    >                 };
    >
    >         for (int i=0; i<elements(ranges); i+=2)
    >             std::fill(table.begin()+ranges+1,
    >                       table.begin()+ranges[i+1]+2,
    >                       true);
    >     }
    >
    >         bool operator[](int n) { return table[unsigned char(n+1)]; }
    >
    > } alpha_table;
    >
    > inline bool is_alphanumeric(int n) {
    >         return alpha_table[n];
    >
    > }
    >
    > This assumes that EOF is -1. Technically this isn't required (any
    > negative value is allowed) but it's extremely common -- to the point
    > that I'm not sure I've ever seen or heard of it actually having any
    > other value. In any case, the reason for the "+1"in most places is to
    > get a range from 0 through the maximum, so we can use it directly as
    > an index into the vector.
    >
    > --
    >     Later,
    >     Jerry.


    Thanks. This is great. A self-contained class like
    this is much better than my #define macro. It's also
    faster since the lookup is immediate rather than
    through a bunch of if-in-range statements.
    Digital Puer, Aug 30, 2009
    #9
    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. luna
    Replies:
    1
    Views:
    6,816
  2. Replies:
    46
    Views:
    966
    Antoon Pardon
    Jul 25, 2006
  3. Lambda
    Replies:
    2
    Views:
    393
    James Kanze
    Jul 16, 2008
  4. Replies:
    6
    Views:
    1,359
    Peter Nilsson
    Oct 26, 2009
  5. Tomoyuki Kosimizu

    Range does not take an Range object.

    Tomoyuki Kosimizu, Nov 25, 2003, in forum: Ruby
    Replies:
    3
    Views:
    151
    Tomoyuki Kosimizu
    Nov 27, 2003
Loading...

Share This Page