Generates integer literal of the largest value a variable can hold.Macro takes only variable-name.

Discussion in 'C Programming' started by John Reye, Apr 23, 2012.

  1. John Reye

    John Reye Guest

    Assume you have a variable called
    var
    of unknown type. (Or that the type can be changed).

    How can one construct a literal, to be the largest value that this
    variable can hold, without information about the variables type?





    #include <stdio.h>
    #define MAX_VALUE_OF_VAR(var) (how should this macro look like, please
    use helper macros if necessary)

    int main()
    {
    signed char var = 0; // only change this line (to other types)
    do {
    ++var;
    printf("%lld, ", (long long int) var);
    } while (var != MAX_VALUE_OF_VAR(var));
    return 0;
    }

    In the above, I currently expect the output to be 1, 2, 3, ..., 127

    If above is changed:
    signed short var = 0;
    .... then I would like the output to be
    1, 2, 3, ..., 32767

    If above is changed:
    signed int var = 0;
    .... and recompile, then I would like the output to be
    1, 2, 3, ..., 2147483647

    etc.


    Is it possible to construct a macro MAX_VALUE_OF_VAR that handles both
    signed and unsigned?
    I've tried and am having a lot of trouble with integer promotions and
    the MSB for negative numbers.

    Is this possible at all.
    Thanks for pointers.
     
    John Reye, Apr 23, 2012
    #1
    1. Advertising

  2. Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    On 23.04.2012 21:38, John Reye wrote:
    > Assume you have a variable called
    > var
    > of unknown type. (Or that the type can be changed).
    >
    > How can one construct a literal, to be the largest value that this
    > variable can hold, without information about the variables type?


    Not in C in a completely portable way. If you are contained to standard
    architectures with binary representation of data, you could check

    a) whether the 1/2 in this variable equals zero or not. If not, it not
    an integer type, otherwise, HUGE_VAL should be the largest possible value,
    b) if (-1) casted to the type is positive, it is unsigned, and the
    result is the largest possible value,
    c) otherwise, on *many standard* systems, you may try to use 1 <<
    ((sizeof(type) << 3)-1) for signed types.

    But as said, this is not portable. In C++, type traits would offer the
    full functionality you need, and even without using the preprocessor.

    So long,
    Thomas
     
    Thomas Richter, Apr 23, 2012
    #2
    1. Advertising

  3. John Reye

    John Reye Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    Ahh that C's right?

    Sortof slightly "statically typed".
    Then then they throw in integer promotions to ease writing code in
    some cases, but causes novice programmer's bugs and kills the type-
    system in other cases.

    Writing portable C-code that works across different word-sizes must be
    a real horror!
     
    John Reye, Apr 23, 2012
    #3
  4. John Reye

    Ben Pfaff Guest

    Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.

    John Reye <> writes:

    > Assume you have a variable called
    > var
    > of unknown type. (Or that the type can be changed).
    >
    > How can one construct a literal, to be the largest value that this
    > variable can hold, without information about the variables type?


    The following works for integer types on "ordinary" sytems.

    /*
    * Copyright (c) 2008, 2011 Nicira Networks.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at:
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */

    #ifndef TYPE_PROPS_H
    #define TYPE_PROPS_H 1

    #include <limits.h>

    #define TYPE_IS_INTEGER(TYPE) ((TYPE) 1.5 == (TYPE) 1)
    #define TYPE_IS_SIGNED(TYPE) ((TYPE) 1 > (TYPE) -1)
    #define TYPE_VALUE_BITS(TYPE) (sizeof(TYPE) * CHAR_BIT - TYPE_IS_SIGNED(TYPE))
    #define TYPE_MINIMUM(TYPE) (TYPE_IS_SIGNED(TYPE) \
    ? ~(TYPE)0 << TYPE_VALUE_BITS(TYPE) \
    : 0)
    #define TYPE_MAXIMUM(TYPE) (TYPE_IS_SIGNED(TYPE) \
    ? ~(~(TYPE)0 << TYPE_VALUE_BITS(TYPE)) \
    : (TYPE)-1)

    /* Number of decimal digits required to format an integer of the given TYPE.
    * Includes space for a sign, if TYPE is signed, but not for a null
    * terminator.
    *
    * The value is an overestimate. */
    #define INT_STRLEN(TYPE) (TYPE_IS_SIGNED(TYPE) + TYPE_VALUE_BITS(TYPE) / 3 + 1)

    #endif /* type-props.h */
     
    Ben Pfaff, Apr 23, 2012
    #4
  5. John Reye

    James Kuyper Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    On 04/23/2012 04:08 PM, Thomas Richter wrote:
    > On 23.04.2012 21:38, John Reye wrote:
    >> Assume you have a variable called
    >> var
    >> of unknown type. (Or that the type can be changed).
    >>
    >> How can one construct a literal, to be the largest value that this
    >> variable can hold, without information about the variables type?

    >
    > Not in C in a completely portable way. If you are contained to standard
    > architectures with binary representation of data, you could check


    The error density in the next sentence is truly amazing. Some people
    consider sentences like this one to be the sign of a troll. I'll
    withhold judgement for now on that issue.

    > a) whether the 1/2 in this variable equals zero or not. ...


    Setting any arithmetic type to 1/2 should produce a result of 0 for all
    arithmetic types. I think you mean 0.5.

    > ... If not, it not
    > an integer type, ...


    This is both simpler and has better grammar: "if so, it is an integer
    type". This would also fix the error in the rest of the sentence:

    > ... otherwise, HUGE_VAL should be the largest possible value,


    I think you got confused by having two many "not"s. As written, assuming
    that you meant 0.5 rather than 1/2, and were thinking of 'double' as the
    only floating point type, that's exactly backwards.

    But that still doesn't work; HUGE_VAL is for doubles, HUGE_VALF and
    HUGE_VALL are for float and long double, respectively. If you knew which
    one of those three options was relevant, that would violate one of the
    specified conditions: no information about the type.

    The HUGE_VAL* macros are special positive values used by the standard
    library for indicating error conditions; their values are otherwise not
    constrained. It's entirely possible for HUGE_VAL to be 1 (though that
    would be a very bad idea).

    > b) if (-1) casted to the type is positive, it is unsigned, and the
    > result is the largest possible value,


    Again, if he knew the type to cast it to, that would violate the
    specified condition: "no information about the type".

    > c) otherwise, on *many standard* systems, you may try to use 1 <<
    > ((sizeof(type) << 3)-1) for signed types.


    Why use "<<3" rather than "*CHAR_BIT"? It's not portable, but it's more
    portable than "<<3".
    You're missing the final -1 in your expression.
     
    James Kuyper, Apr 23, 2012
    #5
  6. John Reye

    James Kuyper Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    On 04/23/2012 04:28 PM, John Reye wrote:
    > Ahh that C's right?
    >
    > Sortof slightly "statically typed".
    > Then then they throw in integer promotions to ease writing code in
    > some cases, but causes novice programmer's bugs and kills the type-
    > system in other cases.
    >
    > Writing portable C-code that works across different word-sizes must be
    > a real horror!


    Not really. If you need exact or minimum sizes, using the size-named
    types from <stdint.h>. If you need C90 capability (or just want to use
    shorter type names), think of [un]signed char as essentially the same as
    int_least8_t, [unsigned] short as int_least16_t, [unsigned] int as
    int_fast16_t, and [unsigned] long as int_least32_t. Except, of
    course, that they're not required to have 2's complement type, and
    (except for unsigned char) are allowed to have padding bits.

    I won't claim it's trivial to deal with all of these issues, but it's
    not a horror. Careful use of the corresponding MIN and MAX macros from
    <stdint.h> or <limits.h> respectively, will deal with most of the
    relevant problems.

    If you want a language that guarantees more about it's fundamental types
    than C does, try Java; but keep in mind the efficiency penalties of
    using a type guaranteed to be exactly 16 bits on a 32-bit machine (or
    vice versa). If that inefficiency doesn't bother you, and the
    corresponding uncertainty about whether 'int' has 16 or 32 bytes does,
    then C is definitely NOT the language for you.
     
    James Kuyper, Apr 23, 2012
    #6
  7. John Reye

    James Kuyper Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    On 04/23/2012 03:38 PM, John Reye wrote:
    > Assume you have a variable called
    > var
    > of unknown type. (Or that the type can be changed).
    >
    > How can one construct a literal, to be the largest value that this
    > variable can hold, without information about the variables type?
    >
    > #include <stdio.h>
    > #define MAX_VALUE_OF_VAR(var) (how should this macro look like, please
    > use helper macros if necessary)
    >
    > int main()
    > {
    > signed char var = 0; // only change this line (to other types)
    > do {
    > ++var;
    > printf("%lld, ", (long long int) var);
    > } while (var != MAX_VALUE_OF_VAR(var));
    > return 0;
    > }
    >
    > In the above, I currently expect the output to be 1, 2, 3, ..., 127
    >
    > If above is changed:
    > signed short var = 0;
    > ... then I would like the output to be
    > 1, 2, 3, ..., 32767
    >
    > If above is changed:
    > signed int var = 0;
    > ... and recompile, then I would like the output to be
    > 1, 2, 3, ..., 2147483647


    Do you have enough time to read that output? Do you have enough paper
    an toner to print it out?

    > Is it possible to construct a macro MAX_VALUE_OF_VAR that handles both
    > signed and unsigned?
    > I've tried and am having a lot of trouble with integer promotions and
    > the MSB for negative numbers.
    >
    > Is this possible at all.


    Not in general.

    For unsigned types, assigning a value of -1 to the variable will set it
    to the maximum value of it's type. Would it be acceptable for the macro
    to change the variable's value? It wouldn't work in your example code -
    would your intended use for this macro allow a re-write to avoid that
    problem? Assigning a value of -1 to a variable is a perfectly safe thing
    to do for all arithmetic types, and testing whether the result is
    greater than 0 is a safe and reliable way of testing for unsignedness.

    If you're willing to make non-portable but very often correct
    assumptions, like 2's complement and no padding bits or trap
    representations, then

    ((long long)pow(2.0,CHAR_BIT*sizeof(var) - 1)-1)

    works for the signed types. If you need portability to systems where
    those assumptions don't apply, you're out of luck.

    The "no type information" approach seems rather odd - it's not something
    that comes up very often in idiomatically written C - you almost always
    know the type of anything you work with, except when using typedefs. It
    sound almost as if you were trying to write a C++ template in C. You
    need to approach problems differently when using C than when using C++.
    If you try to force C to work like C++, you're going to frustrate
    yourself and mystify those who work on your code later, trying to
    implement poor substitutes for genericity in C.
     
    James Kuyper, Apr 23, 2012
    #7
  8. John Reye

    Stefan Ram Guest

    Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.

    John Reye <> writes:
    >How can one construct a literal, to be the largest value that this
    >variable can hold, without information about the variables type?


    The largest value a single bit can hold is not limited.
    It just depends on the code used. For example, I can use this code:

    bit
    state meaning
    0 the number 0
    1 the number 100^100^100^100^100^100^100^100^100^100^100^100^100^100

    For large numbers, see:

    http://www.scottaaronson.com/writings/bignumbers.html
    http://mathoverflow.net/questions/34710/succinctly-naming-big-numbers-zfc-versus-busy-beaver
    http://jeremykun.wordpress.com/2012/02/08/busy-beavers-and-the-quest-for-big-numbers/
    http://en.wikipedia.org/wiki/Busy_beaver
    http://www.strangehorizons.com/2001/20010402/biggest_numbers.shtml
    http://mrob.com/pub/math/largenum-5.html

    . With C, one can use the literal »1«:

    { number c;
    init( &c, 1 );
    print( c ); }

    will print

    100^100^100^100^100^100^100^100^100^100^100^100^100^100

    , given an appropriate definition for »number«, »init«, and »print«
    (exercise).
     
    Stefan Ram, Apr 23, 2012
    #8
  9. John Reye

    John Gordon Guest

    Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.

    In <-berlin.de> -berlin.de (Stefan Ram) writes:

    > The largest value a single bit can hold is not limited.


    That's stretching the meaning of the word "hold", isn't it?

    --
    John Gordon A is for Amy, who fell down the stairs
    B is for Basil, assaulted by bears
    -- Edward Gorey, "The Gashlycrumb Tinies"
     
    John Gordon, Apr 23, 2012
    #9
  10. John Reye

    Stefan Ram Guest

    Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.

    John Gordon <> writes:
    >In <-berlin.de> -berlin.de (Stefan Ram) writes:
    >>The largest value a single bit can hold is not limited.

    >That's stretching the meaning of the word "hold", isn't it?


    What's the largest number a double can hold in your preferred C implementation?

    What's the second largest number it can hold (the next representable number smaller
    than the first)?

    In which sense does a double object »hold« these two values that does not apply
    to the bit I described?
     
    Stefan Ram, Apr 24, 2012
    #10
  11. John Reye

    John Reye Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    Here's a nice hack for... getting the max value for any unsigned type:
    from "unsigned char" to "unsigned long long":

    #include <stdio.h>
    #include <limits.h>

    #define GET_TYPE_INT_OR_LARGER_0(var) (var & 0)

    #define GET_SHIFT_CHAR_BIT2(var) ((sizeof(var) >= sizeof(int)) ? 0 :
    (CHAR_BIT * (sizeof(int)-sizeof(var))))

    /* only unsigned */
    #define GET_MAX_UNSIGNED_RVALUE(var) ((GET_TYPE_INT_OR_LARGER_0(var)
    -1U) >> GET_SHIFT_CHAR_BIT2(var))


    int main(void)
    {
    typedef unsigned long long my_ull;

    my_ull var2;
    printf("%llx\n", GET_MAX_UNSIGNED_RVALUE(var2));

    unsigned i;
    printf("%x\n", GET_MAX_UNSIGNED_RVALUE(i));

    unsigned short s;
    printf("%x\n", GET_MAX_UNSIGNED_RVALUE(s));

    unsigned char c;
    printf("%x\n", GET_MAX_UNSIGNED_RVALUE(c));

    return 0;
    }

    What do you think?

    Does the macro GET_MAX_UNSIGNED_RVALUE() really create a literal?
    (i.e. something that can be used in #if ... preprocessing)
    Or does it depend on the compiler?

    Thanks.
     
    John Reye, May 3, 2012
    #11
  12. John Reye

    Jens Gustedt Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    Am 05/04/2012 12:35 AM, schrieb John Reye:
    > Here's a nice hack for... getting the max value for any unsigned type:
    > from "unsigned char" to "unsigned long long":
    >
    > #include <stdio.h>
    > #include <limits.h>
    >
    > #define GET_TYPE_INT_OR_LARGER_0(var) (var & 0)
    >
    > #define GET_SHIFT_CHAR_BIT2(var) ((sizeof(var) >= sizeof(int)) ? 0 :
    > (CHAR_BIT * (sizeof(int)-sizeof(var))))


    > ....


    > What do you think?
    >
    > Does the macro GET_MAX_UNSIGNED_RVALUE() really create a literal?
    > (i.e. something that can be used in #if ... preprocessing)
    > Or does it depend on the compiler?


    no

    - IIRC ternary expressions are not allowed in the preprocessor
    - sizeof is not evaluated in the preprocessor

    Jens
     
    Jens Gustedt, May 4, 2012
    #12
  13. Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    בת×ריך ×™×•× ×©× ×™,23 ב×פריל 2012 21:28:21 UTC+1, מ×ת John Reye:
    >
    > Writing portable C-code that works across different word-sizes must be
    > a real horror!
    >

    Mostly integers count things. That usually means things in memory.

    Even a char integer, if you think about it, is ultimately going to be used as an index into a table of glyphs.

    So basically you need an integer that can index the largest array you have in memory.

    --
    Basic Algorithms: now also available as an iBook
    http://www.malcolmmclean.site11.com/www
     
    Malcolm McLean, May 4, 2012
    #13
  14. John Reye

    James Kuyper Guest

    Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.

    On 05/04/2012 03:00 AM, Jens Gustedt wrote:
    > Am 05/04/2012 12:35 AM, schrieb John Reye:
    >> Here's a nice hack for... getting the max value for any unsigned type:
    >> from "unsigned char" to "unsigned long long":
    >>
    >> #include <stdio.h>
    >> #include <limits.h>
    >>
    >> #define GET_TYPE_INT_OR_LARGER_0(var) (var & 0)
    >>
    >> #define GET_SHIFT_CHAR_BIT2(var) ((sizeof(var) >= sizeof(int)) ? 0 :
    >> (CHAR_BIT * (sizeof(int)-sizeof(var))))

    >
    >> ....

    >
    >> What do you think?
    >>
    >> Does the macro GET_MAX_UNSIGNED_RVALUE() really create a literal?
    >> (i.e. something that can be used in #if ... preprocessing)
    >> Or does it depend on the compiler?

    >
    > no
    >
    > - IIRC ternary expressions are not allowed in the preprocessor


    The relevant restrictions are implied by the fact that the thing
    following a #if is described by the grammar as a constant-expression.
    "Constant expressions shall not contain assignment, increment,
    decrement, function-call, or comma operators, except when they are
    contained within a subexpression that is not evaluated." (6.6p3)
    The ternary operator ?: is not one of the prohibited ones.

    > - sizeof is not evaluated in the preprocessor


    More precisely, during evaluation of a #if expression, the only
    identifiers that have any special meaning are macros, and "defined".
    Otherwise, "all remaining identifiers (including those lexically
    identical to keywords) are replaced with the pp-number 0" (6.10.1p4) As
    a result, sizeof(int) gets converted into 0(0), which is a syntax error.
    --
    James Kuyper
     
    James Kuyper, May 4, 2012
    #14
  15. John Reye

    Tim Rentsch Guest

    Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.

    John Reye <> writes:

    > Assume you have a variable called
    > var
    > of unknown type. (Or that the type can be changed).
    >
    > How can one construct a literal, to be the largest value that this
    > variable can hold, without information about the variables type?
    > [snip example]


    In C11, all standard numeric types can be handled
    using _Generic. Details left to the reader.
     
    Tim Rentsch, May 8, 2012
    #15
    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. Nicholas

    Largest possible value of Integer Constants

    Nicholas, Sep 11, 2003, in forum: C Programming
    Replies:
    7
    Views:
    414
    Tom Zych
    Sep 12, 2003
  2. D Senthil Kumar

    macro name from macro?

    D Senthil Kumar, Sep 20, 2003, in forum: C Programming
    Replies:
    1
    Views:
    582
    Jack Klein
    Sep 21, 2003
  3. sounak

    to get macro name from macro value

    sounak, Nov 22, 2005, in forum: C Programming
    Replies:
    17
    Views:
    505
    Mark McIntyre
    Nov 22, 2005
  4. Replies:
    3
    Views:
    377
    Tomás
    May 15, 2006
  5. sai krishna
    Replies:
    1
    Views:
    307
    Patricia Shanahan
    Dec 24, 2007
Loading...

Share This Page