Type interchange

Discussion in 'C Programming' started by Edward Rutherford, Nov 30, 2011.

  1. Hello:

    Can the following program generate an undefined behavior?

    Thank you.

    #include<limits.h>
    int main()
    {
    #if INT_MAX == LONG_MAX
    long getchar();
    #else
    int getchar();
    #endif
    (void) getchar();
    return 0;
    }
    Edward Rutherford, Nov 30, 2011
    #1
    1. Advertising

  2. Edward Rutherford

    James Kuyper Guest

    On 11/30/2011 04:53 PM, Edward Rutherford wrote:
    > Hello:
    >
    > Can the following program generate an undefined behavior?
    >
    > Thank you.
    >
    > #include<limits.h>
    > int main()
    > {
    > #if INT_MAX == LONG_MAX
    > long getchar();
    > #else
    > int getchar();
    > #endif
    > (void) getchar();
    > return 0;
    > }


    Programs do not generate undefined behavior. "undefined behavior" does
    not mean a particular kind of behavior. It means that the behavior is
    NOT defined - it can be anything. Code with undefined behavior is
    perfectly capable of behaving in precisely the fashion you incorrectly
    thought it was required to behave.

    Section 7.1.4 says "Provided that a library function can be declared
    without reference to any type defined in a header, it is also
    permissible to declare the function and use it without including its
    associated header.", so the declaration using 'int' is permissible.
    However, 6.5.2.2p9 says " If the function is defined with a type that is
    not compatible with the type (of the expression) pointed to by the
    expression that denotes the called function, the behavior is
    undefined."

    A function declaration that is not a function prototype, and is used in
    a function call expression with no arguments, can be compatible with a
    function defined as taking no parameters - but only if the return types
    are compatible. Nothing in the standard allows you to assume that 'long'
    and 'int' are compatible types, not even if INT_MAX == LONG_MAX. 'int'
    could be a one's complement type, while 'long' is a 2's complement type.
    'int' could be little-endian, while 'long' could be big-endian. When
    used as function arguments, 'int' and 'long' values could be passed in
    different registers.

    None of those possibilities is very likely. In all probability, your
    code will work fine, particularly since it discards the return value,
    unused. However, the fact that it will probably work is NOT guaranteed
    by the standard, the correct wording to describe that absence of a
    guarantee is "the behavior of your program is undefined".
    James Kuyper, Nov 30, 2011
    #2
    1. Advertising

  3. James Kuyper <> writes:
    [...]
    > A function declaration that is not a function prototype, and is used in
    > a function call expression with no arguments, can be compatible with a
    > function defined as taking no parameters - but only if the return types
    > are compatible. Nothing in the standard allows you to assume that 'long'
    > and 'int' are compatible types, not even if INT_MAX == LONG_MAX. 'int'
    > could be a one's complement type, while 'long' is a 2's complement type.
    > 'int' could be little-endian, while 'long' could be big-endian. When
    > used as function arguments, 'int' and 'long' values could be passed in
    > different registers.

    [...]

    The standard defines the term "compatible type". It's clear from
    the standard that int and long are *not* compatible types.

    I think what you mean is that you can't assume that int and
    long have the same representation, alignment requirements, and
    so forth. But even if they do, the behavior of a program that
    declares getchar() as a function returning long is undefined.
    Representation is relevant to how the program is likely to behave
    in practice, but it's not relevant to the question of whether the
    standard define's the code's behavior.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 30, 2011
    #3
  4. Edward Rutherford

    James Kuyper Guest

    On 11/30/2011 06:22 PM, Keith Thompson wrote:
    > James Kuyper <> writes:
    > [...]
    >> A function declaration that is not a function prototype, and is used in
    >> a function call expression with no arguments, can be compatible with a
    >> function defined as taking no parameters - but only if the return types
    >> are compatible. Nothing in the standard allows you to assume that 'long'
    >> and 'int' are compatible types, not even if INT_MAX == LONG_MAX. 'int'
    >> could be a one's complement type, while 'long' is a 2's complement type.
    >> 'int' could be little-endian, while 'long' could be big-endian. When
    >> used as function arguments, 'int' and 'long' values could be passed in
    >> different registers.

    > [...]
    >
    > The standard defines the term "compatible type". It's clear from
    > the standard that int and long are *not* compatible types.


    The standard says that two types are compatible if they're the same. The
    standard has several locations where it specifies that particular pairs
    of types that are not the same are still compatible. There are rules for
    derived types such as arrays, functions, structures, and unions, which
    allow them to be compatible only if the derivations are sufficiently
    similar. However, I couldn't find any place in the normative text where
    it specifies that any particular pair of basic types must be
    incompatible. Footnote 35 says that char, signed char, and unsigned char
    are incompatible types, but I can't find supporting normative text.

    I think that a particular pair of types are in fact compatible for a
    given implementation, if everything that the standard says must work
    when two types are compatible, does in fact work for that pair of types,
    when using that implementation, even if the standard fails to guarantee
    that those types are compatible.

    Could you cite any specific requirement that would be violated by an
    implementation that treated 'int' and 'long' as compatible types?
    James Kuyper, Dec 1, 2011
    #4
  5. James Kuyper <> writes:

    > On 11/30/2011 06:22 PM, Keith Thompson wrote:
    >> James Kuyper <> writes:
    >> [...]
    >>> A function declaration that is not a function prototype, and is used in
    >>> a function call expression with no arguments, can be compatible with a
    >>> function defined as taking no parameters - but only if the return types
    >>> are compatible. Nothing in the standard allows you to assume that 'long'
    >>> and 'int' are compatible types, not even if INT_MAX == LONG_MAX. 'int'
    >>> could be a one's complement type, while 'long' is a 2's complement type.
    >>> 'int' could be little-endian, while 'long' could be big-endian. When
    >>> used as function arguments, 'int' and 'long' values could be passed in
    >>> different registers.

    >> [...]
    >>
    >> The standard defines the term "compatible type". It's clear from
    >> the standard that int and long are *not* compatible types.

    >
    > The standard says that two types are compatible if they're the same. The
    > standard has several locations where it specifies that particular pairs
    > of types that are not the same are still compatible. There are rules for
    > derived types such as arrays, functions, structures, and unions, which
    > allow them to be compatible only if the derivations are sufficiently
    > similar. However, I couldn't find any place in the normative text where
    > it specifies that any particular pair of basic types must be
    > incompatible. Footnote 35 says that char, signed char, and unsigned char
    > are incompatible types, but I can't find supporting normative text.
    >
    > I think that a particular pair of types are in fact compatible for a
    > given implementation, if everything that the standard says must work
    > when two types are compatible, does in fact work for that pair of types,
    > when using that implementation, even if the standard fails to guarantee
    > that those types are compatible.
    >
    > Could you cite any specific requirement that would be violated by an
    > implementation that treated 'int' and 'long' as compatible types?


    I think that is technically impossible since the only things that can
    result from incompatibility are diagnostics and undefined behaviour. If
    an implementation always reported "hey, I treat int and long as
    compatible" it would cover the first, and the second needs no special
    treatment.

    From a quality of implementation point of view, I'd want a diagnostic
    here:

    long l = 0;
    int *ip;
    ip = &l;

    and I'd want it to say that the assignment was the problem due to the
    incompatibility of the pointed-to types (long and int). But, as we
    know, any diagnostic at all (such as the daft one above) will do.

    Types are compatible or not as defined by the standard, and I think it
    muddies the water to talk about types being "compatible for a given
    implementation".

    --
    Ben.
    Ben Bacarisse, Dec 1, 2011
    #5
  6. James Kuyper <> writes:
    > On 11/30/2011 06:22 PM, Keith Thompson wrote:
    >> James Kuyper <> writes:
    >> [...]
    >>> A function declaration that is not a function prototype, and is used in
    >>> a function call expression with no arguments, can be compatible with a
    >>> function defined as taking no parameters - but only if the return types
    >>> are compatible. Nothing in the standard allows you to assume that 'long'
    >>> and 'int' are compatible types, not even if INT_MAX == LONG_MAX. 'int'
    >>> could be a one's complement type, while 'long' is a 2's complement type.
    >>> 'int' could be little-endian, while 'long' could be big-endian. When
    >>> used as function arguments, 'int' and 'long' values could be passed in
    >>> different registers.

    >> [...]
    >>
    >> The standard defines the term "compatible type". It's clear from
    >> the standard that int and long are *not* compatible types.

    >
    > The standard says that two types are compatible if they're the same. The
    > standard has several locations where it specifies that particular pairs
    > of types that are not the same are still compatible. There are rules for
    > derived types such as arrays, functions, structures, and unions, which
    > allow them to be compatible only if the derivations are sufficiently
    > similar. However, I couldn't find any place in the normative text where
    > it specifies that any particular pair of basic types must be
    > incompatible. Footnote 35 says that char, signed char, and unsigned char
    > are incompatible types, but I can't find supporting normative text.


    As I understand it, there doesn't have to be any text that says int
    and long aren't compatible. The fact that nothing says they *are*
    compatible means that they aren't. The definition of "compatible
    types" is spread across 4 different sections, but I believe it's
    intended to be exhaustive. Otherwise, how would you demonstrate
    that *any* pair of types are incompatible?

    > I think that a particular pair of types are in fact compatible for a
    > given implementation, if everything that the standard says must work
    > when two types are compatible, does in fact work for that pair of types,
    > when using that implementation, even if the standard fails to guarantee
    > that those types are compatible.
    >
    > Could you cite any specific requirement that would be violated by an
    > implementation that treated 'int' and 'long' as compatible types?


    If int and long are compatible (even for a particular implementation),
    then int* and long* are also compatible by 6.7.5.1p2. This implies that
    this:

    int *pi = NULL;
    long *pl = pi;
    ptrdiff_t pd = pl - pi;

    does not necessarily violate a constraint. I don't believe that's
    the case; I believe the initialization of pl and the subtraction are
    both constraint violations on all implementations. (That doesn't
    prove that int and long are incompatible, it merely demonstrates
    a consequence if they were.)

    And for what it's worth, gcc agrees with me; it complains

    warning: initialization from incompatible pointer type
    error: invalid operands to binary - (have 'long int *' and 'int *')

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2011
    #6
  7. Edward Rutherford

    James Kuyper Guest

    On 11/30/2011 10:17 PM, Keith Thompson wrote:
    ....
    > As I understand it, there doesn't have to be any text that says int
    > and long aren't compatible. The fact that nothing says they *are*
    > compatible means that they aren't. The definition of "compatible
    > types" is spread across 4 different sections, but I believe it's
    > intended to be exhaustive. Otherwise, how would you demonstrate
    > that *any* pair of types are incompatible?


    The implementation always knows whether two types are incompatible; it
    has to implement them. For the developer, I don't think that it is
    possible to demonstrate from the standard that any pair of basic types
    is incompatible. I think it's very bad practice to write code which
    assumes that two types are compatible without being able to prove that
    they are; but I think it's entirely possible that they are in fact
    compatible for a given implementation, without being able to prove that
    fact from the standard.
    --
    James Kuyper
    James Kuyper, Dec 1, 2011
    #7
  8. Edward Rutherford

    James Kuyper Guest

    On 11/30/2011 10:09 PM, Ben Bacarisse wrote:
    > James Kuyper <> writes:

    ....
    >> I think that a particular pair of types are in fact compatible for a
    >> given implementation, if everything that the standard says must work
    >> when two types are compatible, does in fact work for that pair of types,
    >> when using that implementation, even if the standard fails to guarantee
    >> that those types are compatible.
    >>
    >> Could you cite any specific requirement that would be violated by an
    >> implementation that treated 'int' and 'long' as compatible types?

    >
    > I think that is technically impossible since the only things that can
    > result from incompatibility are diagnostics and undefined behaviour. If
    > an implementation always reported "hey, I treat int and long as
    > compatible" it would cover the first, and the second needs no special
    > treatment.
    >
    > From a quality of implementation point of view, I'd want a diagnostic
    > here:
    >
    > long l = 0;
    > int *ip;
    > ip = &l;
    >
    > and I'd want it to say that the assignment was the problem due to the
    > incompatibility of the pointed-to types (long and int). But, as we
    > know, any diagnostic at all (such as the daft one above) will do.
    >
    > Types are compatible or not as defined by the standard,


    Yes, and the standard leaves the compatibility of types A and B
    unspecified for a very large number of possible pairs of A and B,
    including A='int' and B='long'.

    > ... and I think it
    > muddies the water to talk about types being "compatible for a given
    > implementation".


    It's no muddier than the fact that a given piece of code may have
    undefined behavior on one implementation, and not on another, simply
    because the condition that determines whether or not the behavior is
    undefined depends upon something that's implementation defined:

    unsigned char array[sizeof(long double)];
    array[1] = 1;

    Whether or not that code has undefined behavior depends upon whether or
    not sizeof(long double) > 1, something that is implementation-defined.

    Some people prefer to describe this by saying that if there's any
    possible conforming implementation where the behavior is undefined, then
    the behavior is undefined, period, even on other implementations where
    the condition that makes it undefined isn't true - but I find that
    interpretation incoherent.
    --
    James Kuyper
    James Kuyper, Dec 1, 2011
    #8
  9. James Kuyper <> writes:
    > On 11/30/2011 10:17 PM, Keith Thompson wrote:
    > ...
    >> As I understand it, there doesn't have to be any text that says int
    >> and long aren't compatible. The fact that nothing says they *are*
    >> compatible means that they aren't. The definition of "compatible
    >> types" is spread across 4 different sections, but I believe it's
    >> intended to be exhaustive. Otherwise, how would you demonstrate
    >> that *any* pair of types are incompatible?

    >
    > The implementation always knows whether two types are incompatible; it
    > has to implement them. For the developer, I don't think that it is
    > possible to demonstrate from the standard that any pair of basic types
    > is incompatible. I think it's very bad practice to write code which
    > assumes that two types are compatible without being able to prove that
    > they are; but I think it's entirely possible that they are in fact
    > compatible for a given implementation, without being able to prove that
    > fact from the standard.


    Do you believe that this:

    int *ip = 0;
    long *lp = ip;

    is valid (not a constraint violation) on *any* conforming
    implementation?

    "Compatible types" is a term defined by the standard; it needn't
    conform to the English meanings of the words. What is your basis
    for assuming that the definition is not meant to be exhaustive, and
    that types can be compatible when the standard doesn't say they are?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2011
    #9
  10. Edward Rutherford

    James Kuyper Guest

    On 12/01/2011 10:15 AM, Keith Thompson wrote:
    ....
    > Do you believe that this:
    >
    > int *ip = 0;
    > long *lp = ip;
    >
    > is valid (not a constraint violation) on *any* conforming
    > implementation?
    >
    > "Compatible types" is a term defined by the standard; it needn't
    > conform to the English meanings of the words. What is your basis
    > for assuming that the definition is not meant to be exhaustive, and
    > that types can be compatible when the standard doesn't say they are?


    Mainly it's because 6.2.7p1 says "Additional rules for determining
    whether two types are compatible are described in ...". It does not
    describe them as rules for determining whether types are incompatible.
    If the meaning is as you imply, it would have been clearer to say
    something to the effect that two types not covered by any of these rules
    are incompatible.
    James Kuyper, Dec 1, 2011
    #10
  11. James Kuyper <> writes:

    > On 11/30/2011 10:09 PM, Ben Bacarisse wrote:

    <snip>
    >> Types are compatible or not as defined by the standard,

    >
    > Yes, and the standard leaves the compatibility of types A and B
    > unspecified for a very large number of possible pairs of A and B,
    > including A='int' and B='long'.


    I don't think it does. For your interpretation to be correct the
    standard must fail to say if int and long are the same type. The rule
    is simple:

    "Two types have compatible type if their types are the
    same. Additional rules for determining whether two types are
    compatible..."

    None of the additional rules apply, so all that matters is if we can
    determine whether int and long are or are not the same type. I think it
    is clear that they can't ever be the same type. For example, the
    conversion rank of long is greater than that of int (always). How could
    two types be "the same type" if they differ in such a way? Furthermore,
    we read (in 6.2.5 p4) that

    There are five standard signed integer types, designated as signed
    char, short int, int, long int, and long long int.[1]

    This is not the natural wording to describe these types if two (or more)
    of them may be the same type. Your supposed conforming implementation
    would only have four standard signed integer types.

    <snip>

    [1] 6.7.2 p5 tell us that "long int" and "long" designate the same
    type.

    --
    Ben.
    Ben Bacarisse, Dec 1, 2011
    #11
  12. Edward Rutherford

    James Kuyper Guest

    On 12/01/2011 10:55 AM, Ben Bacarisse wrote:
    > James Kuyper <> writes:
    >
    >> On 11/30/2011 10:09 PM, Ben Bacarisse wrote:

    > <snip>
    >>> Types are compatible or not as defined by the standard,

    >>
    >> Yes, and the standard leaves the compatibility of types A and B
    >> unspecified for a very large number of possible pairs of A and B,
    >> including A='int' and B='long'.

    >
    > I don't think it does. For your interpretation to be correct the
    > standard must fail to say if int and long are the same type. The rule
    > is simple:
    >
    > "Two types have compatible type if their types are the
    > same. Additional rules for determining whether two types are
    > compatible..."


    I never claimed that 'int' and 'long' could be compatible by reason of
    being the same type. When I said that they could be compatible for a
    particular implementation, I meant that this possibility exists despite
    their being different types.

    Some of the other rules referred to by 6.2.7p1 are worded in such a way
    that any pair of types that they apply to which aren't identified as
    compatible by that rule, must be incompatible. For instance, 6.7.3p9
    says "For two qualified types to be compatible, both shall ..."; which
    implies quite clearly that any pair of qualified types that don't match
    the description following the "shall" are not compatible. However,
    neither 'int' nor 'long' is a qualified type, so that doesn't apply.
    Neither do any of the other rules referenced by 6.2.7p1.

    6.2.7p1 itself contains no such wording. It could have been written as:
    For two types to be compatible, they must either be the same type, or
    covered by one of the additional rules in ...". It wasn't written that way.
    James Kuyper, Dec 1, 2011
    #12
  13. Edward Rutherford

    James Kuyper Guest

    On 12/01/2011 11:10 AM, pete wrote:
    > James Kuyper wrote:
    >
    >> Some people prefer to describe this by saying that if there's any
    >> possible conforming implementation
    >> where the behavior is undefined, then
    >> the behavior is undefined, period, even on other implementations where
    >> the condition that makes it undefined isn't true - but I find that
    >> interpretation incoherent.

    >
    > That way,
    > whether or not a program contains undefined behavior
    > is a property of the C program,
    > and not a property of the
    > combination of the implementation and C program.


    Yes, that's a nice feature to have, but it seems incompatible with the
    descriptions given in the standard of the reasons why a given piece of
    code has undefined behavior.

    For example, any attempt to dereference a pointer one-past-the end of an
    array has undefined behavior; but in the example I gave, on any
    implementation where sizeof(long double) > 1, array[1] is NOT an attempt
    to dereference a pointer one past the end of the array - so how could
    such a program qualify has having undefined behavior when translated by
    such an implementation?
    James Kuyper, Dec 1, 2011
    #13
  14. Edward Rutherford

    James Kuyper Guest

    On 12/01/2011 11:04 AM, pete wrote:
    > James Kuyper wrote:
    >>
    >> On 12/01/2011 10:15 AM, Keith Thompson wrote:
    >> ...
    >>> Do you believe that this:
    >>>
    >>> int *ip = 0;
    >>> long *lp = ip;
    >>>
    >>> is valid (not a constraint violation) on *any* conforming
    >>> implementation?
    >>>
    >>> "Compatible types" is a term defined by the standard; it needn't
    >>> conform to the English meanings of the words. What is your basis
    >>> for assuming that the definition is not meant to be exhaustive, and
    >>> that types can be compatible when the standard doesn't say they are?

    >>
    >> Mainly it's because 6.2.7p1 says "Additional rules for determining
    >> whether two types are compatible are described in ...". It does not
    >> describe them as rules for determining whether types are incompatible.
    >> If the meaning is as you imply, it would have been clearer to say
    >> something to the effect that two types not covered
    >> by any of these rules are incompatible.

    >
    > The example of char being compatible
    > neither with signed char nor with unsigned char,
    > should have made it clear enough.


    It makes the intent clear; but since that footnote is not normative, if
    there's no supporting statement in the normative text, that merely means
    that the footnote was wrong, and that the normative words of the
    standard failed to implement the intent of the authors.
    James Kuyper, Dec 1, 2011
    #14
  15. James Kuyper <> writes:

    > On 12/01/2011 10:55 AM, Ben Bacarisse wrote:
    >> James Kuyper <> writes:
    >>
    >>> On 11/30/2011 10:09 PM, Ben Bacarisse wrote:

    >> <snip>
    >>>> Types are compatible or not as defined by the standard,
    >>>
    >>> Yes, and the standard leaves the compatibility of types A and B
    >>> unspecified for a very large number of possible pairs of A and B,
    >>> including A='int' and B='long'.

    >>
    >> I don't think it does. For your interpretation to be correct the
    >> standard must fail to say if int and long are the same type. The rule
    >> is simple:
    >>
    >> "Two types have compatible type if their types are the
    >> same. Additional rules for determining whether two types are
    >> compatible..."

    >
    > I never claimed that 'int' and 'long' could be compatible by reason of
    > being the same type. When I said that they could be compatible for a
    > particular implementation, I meant that this possibility exists despite
    > their being different types.
    >
    > Some of the other rules referred to by 6.2.7p1 are worded in such a way
    > that any pair of types that they apply to which aren't identified as
    > compatible by that rule, must be incompatible. For instance, 6.7.3p9
    > says "For two qualified types to be compatible, both shall ..."; which
    > implies quite clearly that any pair of qualified types that don't match
    > the description following the "shall" are not compatible. However,
    > neither 'int' nor 'long' is a qualified type, so that doesn't apply.
    > Neither do any of the other rules referenced by 6.2.7p1.
    >
    > 6.2.7p1 itself contains no such wording. It could have been written as:
    > For two types to be compatible, they must either be the same type, or
    > covered by one of the additional rules in ...". It wasn't written that
    > way.


    Leaving open the possibility that a conforming implementation might have
    "const char" and "double" as compatible types, or maybe having
    "void (int)" (a function type) be compatible with _Bool *?

    Your point would have been clearer had you chosen one of these more
    dramatic examples.

    --
    Ben.
    Ben Bacarisse, Dec 1, 2011
    #15
  16. Edward Rutherford

    James Kuyper Guest

    On 12/01/2011 11:45 AM, Ben Bacarisse wrote:
    > James Kuyper <> writes:

    ....
    >> 6.2.7p1 itself contains no such wording. It could have been written as:
    >> For two types to be compatible, they must either be the same type, or
    >> covered by one of the additional rules in ...". It wasn't written that
    >> way.

    >
    > Leaving open the possibility that a conforming implementation might have
    > "const char" and "double" as compatible types, or maybe having
    > "void (int)" (a function type) be compatible with _Bool *?
    >
    > Your point would have been clearer had you chosen one of these more
    > dramatic examples.


    The OP asked about 'int' and 'long'. Also, I wasn't sure whether or it
    could be proven, on purely functional grounds, that radically different
    types like those are incapable of being compatible. The standard says
    that a variety of things should work if two types are compatible, and
    I'm not sure that they all could be made to work if, for instance, one
    is a function type and the other is _Bool. It's quite clear to me that
    all of those things could be made to work for int and long, since those
    two types could be identically implemented.
    James Kuyper, Dec 1, 2011
    #16
  17. Edward Rutherford

    Kaz Kylheku Guest

    On 2011-12-01, pete <> wrote:
    > James Kuyper wrote:
    >
    >> Some people prefer to describe this by saying that if there's any
    >> possible conforming implementation
    >> where the behavior is undefined, then
    >> the behavior is undefined, period, even on other implementations where
    >> the condition that makes it undefined isn't true - but I find that
    >> interpretation incoherent.

    >
    > That way,
    > whether or not a program contains undefined behavior
    > is a property of the C program,
    > and not a property of the
    > combination of the implementation and C program.


    That's fair. A program can contain latent undefined behavior (i.e. the
    potential for it) yet depend on the parameters of the implementation
    such that the behavior can be avoided.
    Kaz Kylheku, Dec 1, 2011
    #17
  18. pete <> writes:
    > James Kuyper wrote:
    >> Some people prefer to describe this by saying that if there's any
    >> possible conforming implementation
    >> where the behavior is undefined, then
    >> the behavior is undefined, period, even on other implementations where
    >> the condition that makes it undefined isn't true - but I find that
    >> interpretation incoherent.

    >
    > That way,
    > whether or not a program contains undefined behavior
    > is a property of the C program,
    > and not a property of the
    > combination of the implementation and C program.


    int n = 32767;
    n ++;

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2011
    #18
  19. James Kuyper <> writes:
    > On 12/01/2011 10:55 AM, Ben Bacarisse wrote:
    >> James Kuyper <> writes:
    >>
    >>> On 11/30/2011 10:09 PM, Ben Bacarisse wrote:

    >> <snip>
    >>>> Types are compatible or not as defined by the standard,
    >>>
    >>> Yes, and the standard leaves the compatibility of types A and B
    >>> unspecified for a very large number of possible pairs of A and B,
    >>> including A='int' and B='long'.

    >>
    >> I don't think it does. For your interpretation to be correct the
    >> standard must fail to say if int and long are the same type. The rule
    >> is simple:
    >>
    >> "Two types have compatible type if their types are the
    >> same. Additional rules for determining whether two types are
    >> compatible..."

    >
    > I never claimed that 'int' and 'long' could be compatible by reason of
    > being the same type. When I said that they could be compatible for a
    > particular implementation, I meant that this possibility exists despite
    > their being different types.
    >
    > Some of the other rules referred to by 6.2.7p1 are worded in such a way
    > that any pair of types that they apply to which aren't identified as
    > compatible by that rule, must be incompatible. For instance, 6.7.3p9
    > says "For two qualified types to be compatible, both shall ..."; which
    > implies quite clearly that any pair of qualified types that don't match
    > the description following the "shall" are not compatible. However,
    > neither 'int' nor 'long' is a qualified type, so that doesn't apply.
    > Neither do any of the other rules referenced by 6.2.7p1.
    >
    > 6.2.7p1 itself contains no such wording. It could have been written as:
    > For two types to be compatible, they must either be the same type, or
    > covered by one of the additional rules in ...". It wasn't written that way.


    We know the standard is not 100% internally consistent.

    I think that 6.2.7p1 should have been written as you suggest.
    I think that your suggested wording is consistent with the intent.

    The consequences of another interpretation are, IMHO, quite painful:

    For an implementation where int and long have the same
    representation, they *may or may not* be compatible, depending on
    the implementation. There is no requirement for this choice to
    be documented. Which means that this:

    int *ip = 0;
    long *lp = ip;

    either does or does not violate a constraint, depending on an
    undocumented characteristic of the implementation.

    Furthermore, under your interpretation, I see nothing saying that
    int and long must have the same representation to be compatible.
    An implementation could have 32-bit int and 64-bit long, but if
    it decides that int and long are compatible types, then the above
    declarations may be accepted without so much as a warning.

    My position: The definition of "compatible type" is intended to
    be exhaustive, even though the standard doesn't say so explicitly.
    int and long are incompatible for every implementation (and therefore
    int* and long* are incompatible for every implementation).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2011
    #19
  20. pete <> writes:
    > Keith Thompson wrote:
    >> pete <> writes:
    >> > James Kuyper wrote:
    >> >> Some people prefer to describe this by saying that if there's any
    >> >> possible conforming implementation
    >> >> where the behavior is undefined, then
    >> >> the behavior is undefined, period, even on other implementations where
    >> >> the condition that makes it undefined isn't true - but I find that
    >> >> interpretation incoherent.
    >> >
    >> > That way,
    >> > whether or not a program contains undefined behavior
    >> > is a property of the C program,
    >> > and not a property of the
    >> > combination of the implementation and C program.

    >>
    >> int n = 32767;
    >> n ++;

    >
    > The behavior of that code isn't limited by the standard, is it?


    If INT_MAX == 32767, then its behavior is undefined. Otherwise, its
    behavior is well defined (it sets n to 32768).

    The point is that whether or not a program contains undefined
    behavior already is "a property of the combination of the
    implementation and C program".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2011
    #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. WideBoy
    Replies:
    0
    Views:
    480
    WideBoy
    Jan 4, 2006
  2. Sreejith K

    Interchange 2 nibbles of byte

    Sreejith K, Nov 14, 2003, in forum: C++
    Replies:
    4
    Views:
    485
  3. Bernhard Hidding

    gnuplot parameter interchange

    Bernhard Hidding, Jun 25, 2004, in forum: C++
    Replies:
    3
    Views:
    1,107
    Karl Heinz Buchegger
    Jun 25, 2004
  4. heyo
    Replies:
    3
    Views:
    900
    Dan Pop
    Apr 1, 2004
  5. Bryan
    Replies:
    1
    Views:
    76
Loading...

Share This Page