Direct computation of integer limits in K&R2?

Discussion in 'C Programming' started by santosh, Mar 11, 2008.

  1. santosh

    santosh Guest

    Hello all,

    In K&R2 one exercise asks the reader to compute and print the limits for
    the basic integer types. This is trivial for unsigned types. But is it
    possible for signed types without invoking undefined behaviour
    triggered by overflow? Remember that the constants in limits.h cannot
    be used.
     
    santosh, Mar 11, 2008
    #1
    1. Advertising

  2. santosh

    Ian Collins Guest

    santosh wrote:
    > Hello all,
    >
    > In K&R2 one exercise asks the reader to compute and print the limits for
    > the basic integer types. This is trivial for unsigned types. But is it
    > possible for signed types without invoking undefined behaviour
    > triggered by overflow? Remember that the constants in limits.h cannot
    > be used.
    >

    Isn't it possible to calculate this based on the unsigned types of the
    same size?

    --
    Ian Collins.
     
    Ian Collins, Mar 11, 2008
    #2
    1. Advertising

  3. santosh

    santosh Guest

    Ian Collins wrote:

    > santosh wrote:
    >> Hello all,
    >>
    >> In K&R2 one exercise asks the reader to compute and print the limits
    >> for the basic integer types. This is trivial for unsigned types. But
    >> is it possible for signed types without invoking undefined behaviour
    >> triggered by overflow? Remember that the constants in limits.h cannot
    >> be used.
    >>

    > Isn't it possible to calculate this based on the unsigned types of the
    > same size?


    Won't this require knowledge of the encoding used, whether twos
    complement or sign and magnitude etc?
     
    santosh, Mar 11, 2008
    #3
  4. On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    > Hello all,
    >
    > In K&R2 one exercise asks the reader to compute and print the limits for
    > the basic integer types. This is trivial for unsigned types. But is it
    > possible for signed types without invoking undefined behaviour triggered
    > by overflow? Remember that the constants in limits.h cannot be used.


    #include <stdio.h>
    int main(void) {
    unsigned u = -1;
    int i;
    while ((i = u) < 0 || i != u)
    u = u >> 1;
    printf("INT_MAX == %u\n", u);
    }

    This is not guaranteed to work in C99, where the conversion of an out-of-
    range integer may raise a signal, but it's valid C90, since the result of
    the conversion must be a valid int, and therefore between INT_MIN and
    INT_MAX.
     
    Harald van Dijk, Mar 11, 2008
    #4
  5. santosh

    Ian Collins Guest

    santosh wrote:
    > Ian Collins wrote:
    >
    >> santosh wrote:
    >>> Hello all,
    >>>
    >>> In K&R2 one exercise asks the reader to compute and print the limits
    >>> for the basic integer types. This is trivial for unsigned types. But
    >>> is it possible for signed types without invoking undefined behaviour
    >>> triggered by overflow? Remember that the constants in limits.h cannot
    >>> be used.
    >>>

    >> Isn't it possible to calculate this based on the unsigned types of the
    >> same size?

    >
    > Won't this require knowledge of the encoding used, whether twos
    > complement or sign and magnitude etc?
    >

    I think so, I should have added that.

    --
    Ian Collins.
     
    Ian Collins, Mar 11, 2008
    #5
  6. santosh <> wrote:
    > In K&R2 one exercise asks the reader to compute and
    > print the limits for the basic integer types. This is
    > trivial for unsigned types. But is it possible for
    > signed types without invoking undefined behaviour
    > triggered by overflow? Remember that the constants
    > in limits.h cannot be used.


    Yes. Unlike C99, unsigned to signed integer conversion
    is implementation defined without the possibility of
    raising a signal. So...

    <http://groups.google.com/group/comp.lang.c/msg/ffe17c645660b76c>

    INT_MIN isn't computed per se, rather it's derived by
    determining the representation for negative ints. [I
    know pete posted some very simple constant expressions,
    though it was some time ago.]

    --
    Peter
     
    Peter Nilsson, Mar 11, 2008
    #6
  7. santosh

    santosh Guest

    Harald van D?k wrote:

    > On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    >> Hello all,
    >>
    >> In K&R2 one exercise asks the reader to compute and print the limits
    >> for the basic integer types. This is trivial for unsigned types. But
    >> is it possible for signed types without invoking undefined behaviour
    >> triggered by overflow? Remember that the constants in limits.h cannot
    >> be used.

    >
    > #include <stdio.h>
    > int main(void) {
    > unsigned u = -1;
    > int i;
    > while ((i = u) < 0 || i != u)
    > u = u >> 1;
    > printf("INT_MAX == %u\n", u);
    > }
    >
    > This is not guaranteed to work in C99, where the conversion of an
    > out-of- range integer may raise a signal, but it's valid C90, since
    > the result of the conversion must be a valid int, and therefore
    > between INT_MIN and INT_MAX.


    Thanks. What about the minima?
     
    santosh, Mar 11, 2008
    #7
  8. santosh

    santosh Guest

    Peter Nilsson wrote:

    > santosh <> wrote:
    >> In K&R2 one exercise asks the reader to compute and
    >> print the limits for the basic integer types. This is
    >> trivial for unsigned types. But is it possible for
    >> signed types without invoking undefined behaviour
    >> triggered by overflow? Remember that the constants
    >> in limits.h cannot be used.

    >
    > Yes. Unlike C99, unsigned to signed integer conversion
    > is implementation defined without the possibility of
    > raising a signal. So...
    >
    > <http://groups.google.com/group/comp.lang.c/msg/ffe17c645660b76c>
    >
    > INT_MIN isn't computed per se, rather it's derived by
    > determining the representation for negative ints. [I
    > know pete posted some very simple constant expressions,
    > though it was some time ago.]


    Would you say that this exercise is overly complex for that point in
    K&R2?
     
    santosh, Mar 11, 2008
    #8
  9. On Wed, 12 Mar 2008 03:29:53 +0530, santosh wrote:
    > Harald van D?k wrote:
    >> On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    >>> Hello all,
    >>>
    >>> In K&R2 one exercise asks the reader to compute and print the limits
    >>> for the basic integer types. This is trivial for unsigned types. But
    >>> is it possible for signed types without invoking undefined behaviour
    >>> triggered by overflow? Remember that the constants in limits.h cannot
    >>> be used.

    >>
    >> #include <stdio.h>
    >> int main(void) {
    >> unsigned u = -1;
    >> int i;
    >> while ((i = u) < 0 || i != u)
    >> u = u >> 1;
    >> printf("INT_MAX == %u\n", u);
    >> }
    >>
    >> This is not guaranteed to work in C99, where the conversion of an
    >> out-of- range integer may raise a signal, but it's valid C90, since the
    >> result of the conversion must be a valid int, and therefore between
    >> INT_MIN and INT_MAX.

    >
    > Thanks. What about the minima?


    Up to INT_MIN, you can use this same idea, except start from LONG_MIN
    instead of UINT_MAX. For LONG_MIN, I would cheat with
    strtol("-999999999", 0, 0)
    adding 9s until a range error is returned. :)
     
    Harald van Dijk, Mar 11, 2008
    #9
  10. santosh

    santosh Guest

    Harald van D?k wrote:

    > On Wed, 12 Mar 2008 03:29:53 +0530, santosh wrote:
    >> Harald van D?k wrote:
    >>> On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    >>>> Hello all,
    >>>>
    >>>> In K&R2 one exercise asks the reader to compute and print the
    >>>> limits for the basic integer types. This is trivial for unsigned
    >>>> types. But is it possible for signed types without invoking
    >>>> undefined behaviour triggered by overflow? Remember that the
    >>>> constants in limits.h cannot be used.
    >>>
    >>> #include <stdio.h>
    >>> int main(void) {
    >>> unsigned u = -1;
    >>> int i;
    >>> while ((i = u) < 0 || i != u)
    >>> u = u >> 1;
    >>> printf("INT_MAX == %u\n", u);
    >>> }
    >>>
    >>> This is not guaranteed to work in C99, where the conversion of an
    >>> out-of- range integer may raise a signal, but it's valid C90, since
    >>> the result of the conversion must be a valid int, and therefore
    >>> between INT_MIN and INT_MAX.

    >>
    >> Thanks. What about the minima?

    >
    > Up to INT_MIN, you can use this same idea, except start from LONG_MIN
    > instead of UINT_MAX. For LONG_MIN, I would cheat with
    > strtol("-999999999", 0, 0)
    > adding 9s until a range error is returned. :)


    Okay. I for one am glad that limits.h exists. :)
     
    santosh, Mar 11, 2008
    #10
  11. santosh

    Flash Gordon Guest

    Ian Collins wrote, On 11/03/08 21:54:
    > santosh wrote:
    >> Ian Collins wrote:
    >>
    >>> santosh wrote:
    >>>> Hello all,
    >>>>
    >>>> In K&R2 one exercise asks the reader to compute and print the limits
    >>>> for the basic integer types. This is trivial for unsigned types. But
    >>>> is it possible for signed types without invoking undefined behaviour
    >>>> triggered by overflow? Remember that the constants in limits.h cannot
    >>>> be used.
    >>>>
    >>> Isn't it possible to calculate this based on the unsigned types of the
    >>> same size?

    >> Won't this require knowledge of the encoding used, whether twos
    >> complement or sign and magnitude etc?
    >>

    > I think so, I should have added that.


    Even if you know it is 2s complement you still can't do it. You need to
    know whether sign bit = 1 and all value bits = 0 is a trap or not since
    it is allowed to be a trap representation.
    --
    Flash Gordon
     
    Flash Gordon, Mar 11, 2008
    #11
  12. santosh

    Micah Cowan Guest

    Flash Gordon <> writes:

    > Ian Collins wrote, On 11/03/08 21:54:
    >> santosh wrote:
    >>> Ian Collins wrote:
    >>>
    >>>> santosh wrote:
    >>>>> Hello all,
    >>>>>
    >>>>> In K&R2 one exercise asks the reader to compute and print the limits
    >>>>> for the basic integer types. This is trivial for unsigned types. But
    >>>>> is it possible for signed types without invoking undefined behaviour
    >>>>> triggered by overflow? Remember that the constants in limits.h cannot
    >>>>> be used.
    >>>>>
    >>>> Isn't it possible to calculate this based on the unsigned types of the
    >>>> same size?
    >>> Won't this require knowledge of the encoding used, whether twos
    >>> complement or sign and magnitude etc?
    >>>

    >> I think so, I should have added that.

    >
    > Even if you know it is 2s complement you still can't do it. You need
    > to know whether sign bit = 1 and all value bits = 0 is a trap or not
    > since it is allowed to be a trap representation.


    It's only allowed to be a trap representation on _non_ two's
    complement representations. sign bit = 1 and all value bits = 0 (and
    padding bits at non-trap values) would necessarily be the minimum
    representable value.

    --
    Micah J. Cowan
    Programmer, musician, typesetting enthusiast, gamer...
    http://micah.cowan.name/
     
    Micah Cowan, Mar 12, 2008
    #12
  13. santosh <> wrote:
    > Peter Nilsson wrote:
    > > santosh <> wrote:
    > > > In K&R2 one exercise asks the reader to compute and
    > > > print the limits for the basic integer types. This is
    > > > trivial for unsigned types. But is it possible for
    > > > signed types without invoking undefined behaviour
    > > > triggered by overflow? Remember that the constants
    > > > in limits.h cannot be used.

    > >
    > > Yes. Unlike C99, unsigned to signed integer conversion
    > > is implementation defined without the possibility of
    > > raising a signal. So...
    > >
    > > <http://groups.google.com/group/comp.lang.c/msg/ffe17c645660b76c>
    > >
    > > INT_MIN isn't computed per se, rather it's derived by
    > > determining the representation for negative ints. [I
    > > know pete posted some very simple constant expressions,
    > > though it was some time ago.]


    Quoting pete:

    #if !(1 & -1)
    printf("ones complement\n");
    #elif -1 & 2
    printf("twos complement\n");
    #else
    printf("sign magnitude\n");
    #endif

    Pete asked if greycode or other weird representations
    could be used for negative integers, but it seems that
    is not so, despite the loose wording of C90.
    [cf <http://groups.google.com/group/comp.std.c/msg/5f332b9aa22b92ec>]

    > Would you say that this exercise is overly complex for
    > that point in K&R2?


    [I can't recall the details of K&R2 and I don't have a
    copy on me. I will say...]

    XXXX_MIN is either -XXXX_MAX or -XXXX_MAX-1. Of course, once
    you have LONG_MIN you can determine XXXX_MIN for lower ranked
    types, but I can't see a way of 'computing' LONG_MIN. Inferring
    it from the representation is obviously trivial though.
    [Note that -XXXX_MAX-1 can't be a trap representation in 2c
    under C90.]

    I think most students should be able to create expressions
    to determine representation, though possibly not with the
    simplicity of the ones above on their first attempt.

    --
    Peter
     
    Peter Nilsson, Mar 12, 2008
    #13
  14. santosh

    user923005 Guest

    On Mar 11, 2:37 pm, santosh <> wrote:
    > Hello all,
    >
    > In K&R2 one exercise asks the reader to compute and print the limits for
    > the basic integer types. This is trivial for unsigned types. But is it
    > possible for signed types without invoking undefined behaviour
    > triggered by overflow? Remember that the constants in limits.h cannot
    > be used.


    /*
    The standard hearder <limits.h> was introduced on the same page (36)
    as the exercise.
    We are told to compute the values by standard headers and by direct
    computation.
    We are also told to determine the ranges of the various floating point
    types.

    The only hard part I see is the signed integer min and max values
    without using <limits.h> because I do not see how you can do it
    portably. We can probably deduce the hardware type, but I am not sure
    about what guarantees we have as to internal representation. I guess
    also we will need separate routines for 2's complement, 1's
    complement, sign magnitude, and whatever other types are allowed (e.g.
    is decimal storage allowed? I know of CPUs that had BCD instructions
    in hardware).

    Anyway, here are all the trivial answers:

    */
    #include <stdio.h>
    #include <limits.h>
    #include <float.h>

    void floating_limits(void)
    {
    puts("\nFloating point limits:");
    printf("DBL_DIG %u\n", (unsigned) DBL_DIG);
    printf("DBL_EPSILON %*.*g\n", DBL_DIG + 3, DBL_DIG,
    DBL_EPSILON);
    printf("DBL_MANT_DIG %u\n", (unsigned) DBL_MANT_DIG);
    printf("DBL_MAX %*.*g\n", DBL_DIG + 3, DBL_DIG, DBL_MAX);
    printf("DBL_MAX_10_EXP %u\n", (unsigned) DBL_MAX_10_EXP);
    printf("DBL_MAX_EXP %u\n", (unsigned) DBL_MAX_EXP);
    printf("DBL_MIN %*.*g\n", DBL_DIG + 3, DBL_DIG, DBL_MIN);
    printf("DBL_MIN_10_EXP %d\n", DBL_MIN_10_EXP);
    printf("DBL_MIN_EXP %d\n", DBL_MIN_EXP);
    #ifdef DBL_RADIX
    printf("DBL_RADIX %u\n", (unsigned) DBL_RADIX);
    #endif
    #ifdef DBL_ROUNDS
    printf("DBL_ROUNDS %u\n", (unsigned) DBL_ROUNDS);
    #endif
    printf("FLT_DIG %u\n", (unsigned) FLT_DIG);
    printf("FLT_EPSILON %*.*g\n", FLT_DIG + 3, FLT_DIG,
    FLT_EPSILON);
    #ifdef FLT_GUARD
    printf("FLT_GUARD %u\n", (unsigned) FLT_GUARD);
    #endif
    printf("FLT_MANT_DIG %u\n", (unsigned) FLT_MANT_DIG);
    printf("FLT_MAX %*.*g\n", FLT_DIG + 3, FLT_DIG, FLT_MAX);
    printf("FLT_MAX_10_EXP %u\n", (unsigned) FLT_MAX_10_EXP);
    printf("FLT_MAX_EXP %u\n", (unsigned) FLT_MAX_EXP);
    printf("FLT_MIN %*.*g\n", FLT_DIG + 3, FLT_DIG, FLT_MIN);
    printf("FLT_MIN_10_EXP %d\n", FLT_MIN_10_EXP);
    printf("FLT_MIN_EXP %d\n", FLT_MIN_EXP);
    printf("LDBL_DIG %u\n", (unsigned) LDBL_DIG);
    printf("LDBL_EPSILON %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
    double) LDBL_EPSILON);
    printf("LDBL_MANT_DIG %u\n", (unsigned) LDBL_MANT_DIG);
    printf("LDBL_MAX %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
    double) LDBL_MAX);
    printf("LDBL_MAX_10_EXP %u\n", (unsigned) LDBL_MAX_10_EXP);
    printf("LDBL_MAX_EXP %u\n", (unsigned) LDBL_MAX_EXP);
    printf("LDBL_MIN %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
    double) LDBL_MIN);
    printf("LDBL_MIN_10_EXP %d\n", LDBL_MIN_10_EXP);
    printf("LDBL_MIN_EXP %d\n", LDBL_MIN_EXP);
    #ifdef LDBL_RADIX
    printf("LDBL_RADIX %u\n", (unsigned) LDBL_RADIX);
    #endif
    #ifdef LDBL_ROUNDS
    printf("LDBL_ROUNDS %u\n", (unsigned) LDBL_ROUNDS);
    #endif
    }

    void signed_limits_guarantee(void)
    {
    static const short shrt_min_est = -32767;
    static const short shrt_max_est = +32767;
    static const int int_min_est = -32767;
    static const int int_max_est = +32767;
    static const long long_min_est = -2147483647L;
    static const long long_max_est = +2147483647L;
    static const long long llong_min_est = -9223372036854775807LL;
    static const long long llong_max_est = +9223372036854775807LL;
    puts("\nSigned limits guaranteed by the standard to be at
    least:");
    printf("Signed short min %d\n", shrt_min_est);
    printf("Signed short max %d\n", shrt_max_est);
    printf("Signed int min %d\n", int_min_est);
    printf("Signed int max %d\n", int_max_est);
    printf("Signed long min %ld\n", long_min_est);
    printf("Signed long max %ld\n", long_max_est);
    printf("Signed long long min %lld\n", llong_min_est);
    printf("Signed long long max %lld\n", llong_max_est);

    }

    void limits_lookup(void)
    {
    puts("\nLookup from limits.h:");
    printf("Width of Char %d\n", CHAR_BIT);
    printf("Signed Char max %d\n", CHAR_MAX);
    printf("Signed Char min %d\n", CHAR_MIN);
    printf("Unsigned Char max %d\n", UCHAR_MAX);
    printf("Signed short min %d\n", SHRT_MIN);
    printf("Signed short max %d\n", SHRT_MAX);
    printf("Unsigned short max %u\n", USHRT_MAX);
    printf("Signed int min %d\n", INT_MIN);
    printf("Signed int max %d\n", INT_MAX);
    printf("Unsigned int max %u\n", UINT_MAX);
    printf("Signed long min %ld\n", LONG_MIN);
    printf("Signed long max %ld\n", LONG_MAX);
    printf("Unsigned long max %lu\n", ULONG_MAX);
    printf("Signed long long min %lld\n", LLONG_MIN);
    printf("Signed long long max %lld\n", LLONG_MAX);
    printf("Unsigned long long max %llu\n", ULLONG_MAX);
    }

    void compute_unsigned_max(void)
    {
    unsigned long long ullm = -1;
    unsigned um = -1;
    unsigned long ulm = -1;
    unsigned short usm = -1;
    unsigned char ucm = -1;
    puts("\nSimple computation of unsigned maximums:");
    printf("Unsigned Char max %d\n", ucm);
    printf("Unsigned short max %u\n", usm);
    printf("Unsigned int max %u\n", um);
    printf("Unsigned long max %lu\n", ulm);
    printf("Unsigned long long max %llu\n", ullm);
    }

    int main(void)
    {
    limits_lookup();
    compute_unsigned_max();
    signed_limits_guarantee();
    floating_limits();
    return 0;
    }
     
    user923005, Mar 12, 2008
    #14
  15. santosh

    user923005 Guest

    On Mar 11, 2:54 pm, Harald van D©¦k <> wrote:
    > On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    > > Hello all,

    >
    > > In K&R2 one exercise asks the reader to compute and print the limits for
    > > the basic integer types. This is trivial for unsigned types. But is it
    > > possible for signed types without invoking undefined behaviour triggered
    > > by overflow? Remember that the constants in limits.h cannot be used.

    >
    > #include <stdio.h>
    > int main(void) {
    > unsigned u = -1;
    > int i;
    > while ((i = u) < 0 || i != u)
    > u = u >> 1;
    > printf("INT_MAX == %u\n", u);
    >
    > }
    >
    > This is not guaranteed to work in C99, where the conversion of an out-of-
    > range integer may raise a signal, but it's valid C90, since the result of
    > the conversion must be a valid int, and therefore between INT_MIN and
    > INT_MAX.


    What happens if INT_MAX is larger than UINT_MAX? I see no guarantees
    that this is not possible.
     
    user923005, Mar 12, 2008
    #15
  16. santosh

    Guest

    On Mar 11, 7:30 pm, Micah Cowan <> wrote:
    > Flash Gordon <> writes:
    > > Ian Collins wrote, On 11/03/08 21:54:
    > >> santosh wrote:
    > >>> Ian Collins wrote:

    >
    > >>>> santosh wrote:
    > >>>>> Hello all,

    >
    > >>>>> In K&R2 one exercise asks the reader to compute and print the limits
    > >>>>> for the basic integer types. This is trivial for unsigned types. But
    > >>>>> is it possible for signed types without invoking undefined behaviour
    > >>>>> triggered by overflow? Remember that the constants in limits.h cannot
    > >>>>> be used.

    >
    > >>>> Isn't it possible to calculate this based on the unsigned types of the
    > >>>> same size?
    > >>> Won't this require knowledge of the encoding used, whether twos
    > >>> complement or sign and magnitude etc?

    >
    > >> I think so, I should have added that.

    >
    > > Even if you know it is 2s complement you still can't do it. You need
    > > to know whether sign bit = 1 and all value bits = 0 is a trap or not
    > > since it is allowed to be a trap representation.

    >
    > It's only allowed to be a trap representation on _non_ two's
    > complement representations. sign bit = 1 and all value bits = 0 (and
    > padding bits at non-trap values) would necessarily be the minimum
    > representable value.


    6.5.6.2p2 says ("the first two" below are sign-and-magnitude and
    two's complement):

    "Which of these applies is implementation-defined, as is whether the
    value with sign bit 1 and all value bits zero (for the first two),
    or with sign bit and all value bits 1 (for ones' complement), is a
    trap representation or a normal value."
     
    , Mar 12, 2008
    #16
  17. santosh

    Guest

    On Mar 11, 10:15 pm, user923005 <> wrote:
    > On Mar 11, 2:54 pm, Harald van D©¦k <> wrote:
    >
    >
    >
    > > On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
    > > > Hello all,

    >
    > > > In K&R2 one exercise asks the reader to compute and print the limits for
    > > > the basic integer types. This is trivial for unsigned types. But is it
    > > > possible for signed types without invoking undefined behaviour triggered
    > > > by overflow? Remember that the constants in limits.h cannot be used.

    >
    > > #include <stdio.h>
    > > int main(void) {
    > > unsigned u = -1;
    > > int i;
    > > while ((i = u) < 0 || i != u)
    > > u = u >> 1;
    > > printf("INT_MAX == %u\n", u);

    >
    > > }

    >
    > > This is not guaranteed to work in C99, where the conversion of an out-of-
    > > range integer may raise a signal, but it's valid C90, since the result of
    > > the conversion must be a valid int, and therefore between INT_MIN and
    > > INT_MAX.

    >
    > What happens if INT_MAX is larger than UINT_MAX? I see no guarantees
    > that this is not possible.


    6.2.6.2p1-2 say that: INT_MAX = 2**M - 1, UINT_MAX = 2**N - 1,
    and M <= N, where M is the number of value bits in int, N is
    the number of value bits in unsigned int.
    I wonder if there was an implementation where INT_MAX was
    equal to UINT_MAX.

    Yevgen
     
    , Mar 12, 2008
    #17
  18. santosh

    user923005 Guest

    On Mar 11, 2:37 pm, santosh <> wrote:
    > Hello all,
    >
    > In K&R2 one exercise asks the reader to compute and print the limits for
    > the basic integer types. This is trivial for unsigned types. But is it
    > possible for signed types without invoking undefined behaviour
    > triggered by overflow? Remember that the constants in limits.h cannot
    > be used.


    Here are some int maximum estimators (seems chummy at best because it
    assumes that larger -> smaller integer assignments won't cause trap
    representiation):

    #include <stdio.h>
    typedef enum itype {
    chartype, shorttype, inttype, longtype, longlongtype
    } itypes;

    unsigned long long bsearch_limit(itypes i)
    {
    unsigned long long ullmax = -1;
    unsigned long long ullmin = 0;
    unsigned long long p;
    long long lla;
    long la;
    int ia;
    short sa;
    char ca;
    if (i == longlongtype)
    return 9223372036854775807LL;
    do {
    p = ((ullmax + ullmin) >> 1);
    switch (i) {
    case chartype:
    ca = p;
    if (ca != p) {
    ullmax = p;
    } else {
    ullmin = p;
    }
    break;
    case shorttype:
    sa = p;
    if (sa != p) {
    ullmax = p;
    } else {
    ullmin = p;
    }
    break;
    case inttype:
    ia = p;
    if (ia != p) {
    ullmax = p;
    } else {
    ullmin = p;
    }
    break;
    case longtype:
    la = p;
    if (la != p) {
    ullmax = p;
    } else {
    ullmin = p;
    }
    break;
    }
    if ((ullmax - ullmin) == 1) {
    switch (i) {
    case chartype:
    ca = ullmax;
    if (ca != ullmax) {
    return ullmin;
    } else {
    return ullmax;
    }
    break;
    case shorttype:
    sa = ullmax;
    if (sa != ullmax) {
    return ullmin;
    } else {
    return ullmax;
    }
    break;
    case inttype:
    ia = ullmax;
    if (ia != ullmax) {
    return ullmin;
    } else {
    return ullmax;
    }
    break;
    case longtype:
    la = ullmax;
    if (la != ullmax) {
    return ullmin;
    } else {
    return ullmax;
    }
    break;
    }

    }
    } while (ullmax > ullmin);
    return ullmax;
    }

    unsigned long long int_limit(itypes i)
    {
    unsigned long long u = -1;

    if (i == chartype) {
    char s = u;
    if (u >= s) {
    while ((s = u) < 0 || s != u)
    u >>= 1;
    return u;
    }
    } else if (i == shorttype) {
    short s = u;
    if (u >= s) {
    while ((s = u) < 0 || s != u)
    u >>= 1;
    return u;
    }
    } else if (i == inttype) {
    int s = u;
    if (u >= s) {
    while ((s = u) < 0 || s != u)
    u >>= 1;
    return u;
    }
    } else if (i == longtype) {
    long s = u;
    if (u >= s) {
    while ((s = u) < 0 || s != u)
    u >>= 1;
    return u;
    }
    } else if (i == longlongtype) {
    long long s = u;
    if (u >= s) {
    while ((s = u) < 0 || s != u)
    u >>= 1;
    return u;
    }
    }
    return 0;
    }

    int main(void)
    {
    printf("Signed char max %llu\n", int_limit(chartype));
    printf("Signed short max %llu\n", int_limit(shorttype));
    printf("Signed int max %llu\n", int_limit(inttype));
    printf("Signed long max %llu\n", int_limit(longtype));
    printf("Signed long long max %llu\n", int_limit(longlongtype));

    printf("Signed char max %llu\n", bsearch_limit(chartype));
    printf("Signed short max %llu\n", bsearch_limit(shorttype));
    printf("Signed int max %llu\n", bsearch_limit(inttype));
    printf("Signed long max %llu\n", bsearch_limit(longtype));
    printf("Signed long long max %llu\n",
    bsearch_limit(longlongtype));
    return 0;
    }
     
    user923005, Mar 12, 2008
    #18
  19. santosh

    CBFalconer Guest

    Harald van D?k wrote:
    > santosh wrote:
    >
    >> In K&R2 one exercise asks the reader to compute and print the
    >> limits for the basic integer types. This is trivial for unsigned
    >> types. But is it possible for signed types without invoking
    >> undefined behaviour triggered by overflow? Remember that the
    >> constants in limits.h cannot be used.

    >
    > #include <stdio.h>
    > int main(void) {
    > unsigned u = -1;
    > int i;
    > while ((i = u) < 0 || i != u)
    > u = u >> 1;
    > printf("INT_MAX == %u\n", u);
    > }
    >
    > This is not guaranteed to work in C99, where the conversion of
    > an out-of- range integer may raise a signal, but it's valid C90,
    > since the result of the conversion must be a valid int, and
    > therefore between INT_MIN and INT_MAX.


    This CAN'T work everywhere. The u = -1 statement is legal, and
    results in UINT_MAX value. However the first i = u statement
    always overruns the INT_MAX value for i, unless the system has
    INT_MAX defined to be equal to UINT_MAX. Very rare. So the result
    of that statement is implementation defined.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Mar 12, 2008
    #19
  20. santosh

    Ark Khasin Guest

    Peter Nilsson wrote:
    > Quoting pete:
    >
    > #if !(1 & -1)
    > printf("ones complement\n");
    > #elif -1 & 2
    > printf("twos complement\n");
    > #else
    > printf("sign magnitude\n");
    > #endif
    >
    > Pete asked if greycode or other weird representations
    > could be used for negative integers, but it seems that
    > is not so, despite the loose wording of C90.
    > [cf <http://groups.google.com/group/comp.std.c/msg/5f332b9aa22b92ec>]
    >

    Is there any assurance that the representation of integer constants in
    the preprocessor is
    - in any way related to the representation of integer objects
    - falls into one of the three models of representation of integer objects
    ?
    [Of course the above can be repaired so as to not use the preprocessor.
    Just asking...]
    -- Ark
     
    Ark Khasin, Mar 12, 2008
    #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. walala
    Replies:
    2
    Views:
    2,328
    joris
    Mar 24, 2010
  2. le Cl?
    Replies:
    15
    Views:
    3,155
    Michel
    Apr 11, 2009
  3. Jesper Sahner

    "Symbolic computation"

    Jesper Sahner, Oct 23, 2004, in forum: Java
    Replies:
    3
    Views:
    446
  4. Aaron Fude
    Replies:
    10
    Views:
    574
    Mark Thornton
    Dec 20, 2004
  5. Replies:
    2
    Views:
    471
Loading...

Share This Page