Integer promotion, relational operators, and unequal integer ranks.

Discussion in 'C Programming' started by charles_gero@merck.com, Jan 15, 2007.

  1. Guest

    Hi all,

    I had a question about the topics in the subject and posted to
    comp.std.c, but feel it may also be appropriate here. Please excuse
    this crosspost if it is in bad form.

    I have a question about whether or not I am interpreting a nuance of
    the standard correctly, and the implications of said nuance. The
    sections in the C99 standard (and possibly older standards) that I will
    reference are as follows (typed out hopefully to avoid people having to
    flip through their own manuals; if you want to fast forward to the meat
    of this post, skip down to "-------end reference-------" line):

    -------begin reference-------
    6.2.6.2p2 (specifically):

    For signed integer types, the bits of the object representation shall
    be divided into three groups: value bits, padding bits, and the sign
    bit. There need not be any padding bits; there shall be exactly one
    sign bit. Each bit that is a value bit shall have the same value as the
    same bit in the object representation of the corresponding unsigned
    type (if there are M value bits in the signed type and N in the
    unsigned type, then M≤N)...

    6.3.1.1p1:

    Every integer type has an integer conversion rank defined as follows:

    —No two signed integer types shall have the same rank, even if they
    have the same representation.
    —The rank of a signed integer type shall be greater than the rank of
    any signed integer type with less precision.
    —The rank of long long int shall be greater than the rank of long
    int, which shall be greater than the rank of int, which shall be
    greater than the rank of short int, which shall be greater than the
    rank of signed char.
    —The rank of any unsigned integer type shall equal the rank of the
    corresponding signed integer type, if any.
    —The rank of any standard integer type shall be greater than the rank
    of any extended integer type with the same width.
    —The rank of char shall equal the rank of signed char and unsigned
    char.
    —The rank of_Bool shall be less than the rank of all other standard
    integer types.
    —The rank of any enumerated type shall equal the rank of the
    compatible integer type (see 6.7.2.2).
    —The rank of any extended signed integer type relative to another
    extended signed integer type with the same precision is
    implementation-defined, but still subject to the other rules for
    determining the integer conversion rank.
    —For all integer types T1, T2, andT3, if T1 has greater rank than T2
    and T2 has greater rank than T3, then T1 has greater rank than T3.

    6.3.1.8p1 (specifically):

    Otherwise, the integer promotions are performed on both operands. Then
    the following rules are applied to the promoted operands:

    If both operands have the same type, then no further conversion is
    needed.

    Otherwise, if both operands have signed integer types or both have
    unsigned integer types, the operand with the type of lesser integer
    conversion rank is converted to the type of the operand with greater
    rank.

    Otherwise, if the operand that has unsigned integer type has rank
    greater or equal to the rank of the type of the other operand, then the
    operand with signed integer type is converted to the type of the
    operand with unsigned
    integer type.

    Otherwise, if the type of the operand with signed integer type can
    represent all of the values of the type of the operand with unsigned
    integer type, then the operand with unsigned integer type is converted
    to the type of the
    operand with signed integer type.

    Otherwise, both operands are converted to the unsigned integer type
    corresponding to the type of the operand with signed integer type.

    6.5.8p3

    If both of the operands have arithmetic type, the usual arithmetic
    conversions are performed.
    -------end reference-------

    Alright, now for the background. While redoing some string libraries I
    had created a while back, I ran across some interesting check code that
    I had added and now feel may be subject to an oddity. We all know that
    the return type of snprintf is int (I assume for historical reasons and
    the fact that a negative is used to indicate failure) as opposed to a
    size_t. In this library I had code that does the following check
    (where n is a non negative return value from a prior snprintf call used
    to determine the size of the required storage):

    if ( n >= SIZE_MAX )
    {
    .... return error information indicating that the size required will not
    appropriately fit into a size_t and thusly I can not call malloc...

    }

    The assumption was that there is nothing in the standard to my
    knowledge that prohibits a size_t being typedef'd to an unsigned type
    incapable of holding the full positive range of an int. I believe my
    past assumption was that integer promotion would be performed in this
    relational expression and that the expression would always work. I'm
    now beginning to question the always work portion. If I'm reading the
    above referenced sections correctly, it is completely possible for an
    implementation to have the following setup:

    size_t typedef'd to an unsigned type with lower rank than an int.
    Following the above rules, if we assume that in this implementation
    there is a corresponding signed type, then both the size_t and the
    signed type would have equal rank. Let us call this rank R1. int and
    unsigned int have equal and higher rank than R1, lets call this R2.
    Let A be the precision of the size_t, B be the precision of the
    corresponding size_t signed type, C be the precision of an unsigned
    int, and D be the precision of an int.

    According to the above mentioned rules then,

    R2 > R1
    A >= B (Rank R1) [6.2.6.2p2]
    C >= D (Rank R2) [6.2.6.2p2]
    D >= B [6.3.1.1p1]

    Therefor, there is no way to link A and C relationally. It is entirely
    possible to have the size_t have greater precision than the unsigned
    int, even though the unsigned int is higher ranked (seems counter
    intuitive but if I'm correct, this is true). Therefor, in my original
    comparison, if we're on an implementation where this is true, and where
    an int can not sufficiently hold all the values of a size_t, than
    according to 6.3.1.8p1, *both operands are converted to the unsigned
    integer type corresponding to the type of the operand with signed
    integer type*, in this case unsigned int. Therefor, the size_t
    (SIZE_MAX) would get converted to a type incapable of holding that
    value, and the value would wrap around to a smaller number and thus
    possibly give incorrect results.

    Can someone very familiar with the standards tell me if my assumption
    is correct. I know I've written a book in this post and apologize, I
    just find it difficult to explain without the elaboration. If it is
    true, do their exist any ways to safely compare values of an unsigned
    type in a lower rank to values of a signed type in a higher rank
    without any possible "overflow" of the value in the converted type?

    Any insight would be massively appreciated!

    Thanks so much!

    -Charlie
    , Jan 15, 2007
    #1
    1. Advertising

  2. wrote:

    You better recheck this, but

    > 6.3.1.8p1 (specifically):
    >
    > Otherwise, the integer promotions are performed on both operands. Then
    > the following rules are applied to the promoted operands:


    which means that SIZE_MAX will be at least promoted to unsigned int.
    christian.bau, Jan 15, 2007
    #2
    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. Konrad Thor
    Replies:
    0
    Views:
    290
    Konrad Thor
    Sep 4, 2004
  2. Paul McGuire
    Replies:
    2
    Views:
    352
    Ville Vainio
    Oct 27, 2004
  3. swansnow

    operators and type promotion

    swansnow, Dec 12, 2007, in forum: C Programming
    Replies:
    4
    Views:
    300
    swansnow
    Dec 12, 2007
  4. Replies:
    1
    Views:
    549
    James Kanze
    Apr 12, 2009
  5. Ganesh Gopalakrishnan
    Replies:
    1
    Views:
    132
    Ganesh Gopalakrishnan
    Oct 17, 2011
Loading...

Share This Page