What is happening in “? :”? I have no idea about the return type












18















I think ((1 ? (int)1 : (unsigned int)2) > -1) results in 1 (true), but actually it is 0 (false) in Visual Studio 2017.



I think the value of (1 ? (int)1 : (unsigned int)2) should be (int)1, because 1 ? is true, and 1 > -1 would be true.



I don't know the reason why the final result of this expression is false.



When I try casting like ((int)(1 ? (int)1 : (unsigned int)2) > -1), it returns 1 (true).



signed int test = -1;
signed int si = 1;
unsigned int ui = 2;

printf("%dn", ((1 ? si : ui) > test));
return 0;


I expect the output to be 1, but the actual output is 0.










share|improve this question




















  • 7





    The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

    – pmg
    Jan 6 at 14:30








  • 1





    Possible duplicate of Comparison operation on unsigned and signed integers

    – manjy
    Jan 6 at 14:36






  • 5





    @manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

    – Eric Postpischil
    Jan 6 at 15:03
















18















I think ((1 ? (int)1 : (unsigned int)2) > -1) results in 1 (true), but actually it is 0 (false) in Visual Studio 2017.



I think the value of (1 ? (int)1 : (unsigned int)2) should be (int)1, because 1 ? is true, and 1 > -1 would be true.



I don't know the reason why the final result of this expression is false.



When I try casting like ((int)(1 ? (int)1 : (unsigned int)2) > -1), it returns 1 (true).



signed int test = -1;
signed int si = 1;
unsigned int ui = 2;

printf("%dn", ((1 ? si : ui) > test));
return 0;


I expect the output to be 1, but the actual output is 0.










share|improve this question




















  • 7





    The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

    – pmg
    Jan 6 at 14:30








  • 1





    Possible duplicate of Comparison operation on unsigned and signed integers

    – manjy
    Jan 6 at 14:36






  • 5





    @manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

    – Eric Postpischil
    Jan 6 at 15:03














18












18








18


2






I think ((1 ? (int)1 : (unsigned int)2) > -1) results in 1 (true), but actually it is 0 (false) in Visual Studio 2017.



I think the value of (1 ? (int)1 : (unsigned int)2) should be (int)1, because 1 ? is true, and 1 > -1 would be true.



I don't know the reason why the final result of this expression is false.



When I try casting like ((int)(1 ? (int)1 : (unsigned int)2) > -1), it returns 1 (true).



signed int test = -1;
signed int si = 1;
unsigned int ui = 2;

printf("%dn", ((1 ? si : ui) > test));
return 0;


I expect the output to be 1, but the actual output is 0.










share|improve this question
















I think ((1 ? (int)1 : (unsigned int)2) > -1) results in 1 (true), but actually it is 0 (false) in Visual Studio 2017.



I think the value of (1 ? (int)1 : (unsigned int)2) should be (int)1, because 1 ? is true, and 1 > -1 would be true.



I don't know the reason why the final result of this expression is false.



When I try casting like ((int)(1 ? (int)1 : (unsigned int)2) > -1), it returns 1 (true).



signed int test = -1;
signed int si = 1;
unsigned int ui = 2;

printf("%dn", ((1 ? si : ui) > test));
return 0;


I expect the output to be 1, but the actual output is 0.







c ternary-operator unsigned signed conditional-operator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 7 at 3:16









Deduplicator

34.4k64888




34.4k64888










asked Jan 6 at 14:15









BellSnowBellSnow

995




995








  • 7





    The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

    – pmg
    Jan 6 at 14:30








  • 1





    Possible duplicate of Comparison operation on unsigned and signed integers

    – manjy
    Jan 6 at 14:36






  • 5





    @manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

    – Eric Postpischil
    Jan 6 at 15:03














  • 7





    The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

    – pmg
    Jan 6 at 14:30








  • 1





    Possible duplicate of Comparison operation on unsigned and signed integers

    – manjy
    Jan 6 at 14:36






  • 5





    @manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

    – Eric Postpischil
    Jan 6 at 15:03








7




7





The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

– pmg
Jan 6 at 14:30







The type of (WHATEVER ? (int)1 : (double)42) is always the same. The type does not change when you change WHATEVER. See c99 6.5.15.

– pmg
Jan 6 at 14:30






1




1





Possible duplicate of Comparison operation on unsigned and signed integers

– manjy
Jan 6 at 14:36





Possible duplicate of Comparison operation on unsigned and signed integers

– manjy
Jan 6 at 14:36




5




5





@manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

– Eric Postpischil
Jan 6 at 15:03





@manjy: This is not a duplicate of that. That question, and its best answer, address binary operators. First, ? : is not a binary operator, and, regardless of the value of its first operand, the last two operands are not combined in an operation. It is true that the usual arithmetic conversions apply when ? : has arithmetic operands, but that question does not say that, since it is not discussing the ? : operator. (Additionally, ? : may have non-arithmetic operands.)

– Eric Postpischil
Jan 6 at 15:03












4 Answers
4






active

oldest

votes


















19














The type of a ? b : c is not dependent on a. It is determined unconditionally by the types of b and c. The full rules are complicated, but, for arithmetic operands, the type is determined by the usual arithmetic conversions. In effect, the two operands are converted to a common type. For int and unsigned int, the resulting type is unsigned int.



The conditional operator, ? : is described in clause 6.5.15 of the C 2018 standard. Paragraph 4 says the result is “converted to the type described below.”



Paragraph 5 describes the result for arithmetic types, structures, and unions:




If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.




Arithmetic types are integer and floating-point types, per 6.2.5 18. (These include both real and complex types.) The usual arithmetic conversions are described in 6.3.1.8 1, which are (in my summary, not quoted):




  • If either is a complex type, the result is complex, and the remaining rules describe the type of the real and imaginary parts. Otherwise, the result is real, and the remaining rules describe its type.

  • If either is long double, the result is long double.

  • Otherwise, if either is double, the result is double.

  • Otherwise, if either is float, the result is float.

  • Otherwise, the integer promotions are applied to each operand (these are specified in 6.3.1.1 2), and then the two types are converted to a common integer type. The full rules for this are somewhat complicated, use a concept of rank that requires some explanation, and cover some esoteric situations, so I will just summarize them for normal situations: If both types are int or narrower (meaning fewer bits or the same number of bits but signed instead of unsigned), the result is int. Otherwise, if both are unsigned int or narrower, the result is unsigned int. Otherwise, the result is the wider type.


The structure, union, and void rules are clear: The two operands must have the same type, and that is the result.



Paragraph 6 describes the result for pointers:




If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.




In summary, that says:




  • If either operand has qualifiers (const, volatile, restrict, or _Atomic), include those in the result type.

  • If the two types are different but compatible (such as an array of unknown size and an array of known size, both with the same type of elements), then combine the two types. (Other possibilities for combining, besides array size, include the elements of the arrays being different but compatible types, a function with and without a parameter list, and the parameters to functions being different but compatible types.)






share|improve this answer


























  • So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

    – BellSnow
    Jan 6 at 15:08











  • @BellSnow: Yes.

    – Eric Postpischil
    Jan 6 at 15:44



















2














You should not mix signed and unsigned values unless you perfectly know what is unfolding (and you want that behavior) [checkout here why]. Behind the scenes, as you have an unsigned number in your expression, C is evaluated your greater-than operator to an unsigned integer >. Therefore, your comparison will not evaluate true as "unsigned -1" is greater than your unsigned 1.






share|improve this answer



















  • 1





    OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

    – Eric Postpischil
    Jan 6 at 14:59











  • Indeed. I was writing in a general sense.

    – delirium
    Jan 6 at 15:01






  • 1





    Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

    – chqrlie
    Jan 6 at 15:44













  • @chqrlie exactly! That behavior is even harder to bug.

    – delirium
    Jan 7 at 10:48











  • @delirium: to bug or to debug, that is the question... :)

    – chqrlie
    Jan 7 at 13:46





















1














The result of your ?: operator has unsigned type, since it is the common type for int and unsigned (your 2nd and 3rd operands). The result has the "expected" value of 1, but its type is unsigned.



The rest has nothing to do with ?: at all. It is well-described in numerous answers for this frequently asked question: Comparison operation on unsigned and signed integers






share|improve this answer

































    0














    Just to put a number on it, if I drop this code:



    unsigned x = (unsigned)-1;


    into a program I'm debugging right now, X has the value 4294967295 (UINT_MAX), i.e. your program "sees" the comparison as something like this:



    ((1 ? (int)1 : (unsigned int)2) > 4294967296)


    (Would have entered this as a comment, but I don't have the reputation.)






    share|improve this answer
























    • just use -1U or 2U instead of (unsigned)-1;...

      – phuclv
      Jan 7 at 1:26






    • 1





      This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

      – M.M
      Jan 7 at 4:19











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54062382%2fwhat-is-happening-in-i-have-no-idea-about-the-return-type%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    19














    The type of a ? b : c is not dependent on a. It is determined unconditionally by the types of b and c. The full rules are complicated, but, for arithmetic operands, the type is determined by the usual arithmetic conversions. In effect, the two operands are converted to a common type. For int and unsigned int, the resulting type is unsigned int.



    The conditional operator, ? : is described in clause 6.5.15 of the C 2018 standard. Paragraph 4 says the result is “converted to the type described below.”



    Paragraph 5 describes the result for arithmetic types, structures, and unions:




    If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.




    Arithmetic types are integer and floating-point types, per 6.2.5 18. (These include both real and complex types.) The usual arithmetic conversions are described in 6.3.1.8 1, which are (in my summary, not quoted):




    • If either is a complex type, the result is complex, and the remaining rules describe the type of the real and imaginary parts. Otherwise, the result is real, and the remaining rules describe its type.

    • If either is long double, the result is long double.

    • Otherwise, if either is double, the result is double.

    • Otherwise, if either is float, the result is float.

    • Otherwise, the integer promotions are applied to each operand (these are specified in 6.3.1.1 2), and then the two types are converted to a common integer type. The full rules for this are somewhat complicated, use a concept of rank that requires some explanation, and cover some esoteric situations, so I will just summarize them for normal situations: If both types are int or narrower (meaning fewer bits or the same number of bits but signed instead of unsigned), the result is int. Otherwise, if both are unsigned int or narrower, the result is unsigned int. Otherwise, the result is the wider type.


    The structure, union, and void rules are clear: The two operands must have the same type, and that is the result.



    Paragraph 6 describes the result for pointers:




    If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.




    In summary, that says:




    • If either operand has qualifiers (const, volatile, restrict, or _Atomic), include those in the result type.

    • If the two types are different but compatible (such as an array of unknown size and an array of known size, both with the same type of elements), then combine the two types. (Other possibilities for combining, besides array size, include the elements of the arrays being different but compatible types, a function with and without a parameter list, and the parameters to functions being different but compatible types.)






    share|improve this answer


























    • So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

      – BellSnow
      Jan 6 at 15:08











    • @BellSnow: Yes.

      – Eric Postpischil
      Jan 6 at 15:44
















    19














    The type of a ? b : c is not dependent on a. It is determined unconditionally by the types of b and c. The full rules are complicated, but, for arithmetic operands, the type is determined by the usual arithmetic conversions. In effect, the two operands are converted to a common type. For int and unsigned int, the resulting type is unsigned int.



    The conditional operator, ? : is described in clause 6.5.15 of the C 2018 standard. Paragraph 4 says the result is “converted to the type described below.”



    Paragraph 5 describes the result for arithmetic types, structures, and unions:




    If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.




    Arithmetic types are integer and floating-point types, per 6.2.5 18. (These include both real and complex types.) The usual arithmetic conversions are described in 6.3.1.8 1, which are (in my summary, not quoted):




    • If either is a complex type, the result is complex, and the remaining rules describe the type of the real and imaginary parts. Otherwise, the result is real, and the remaining rules describe its type.

    • If either is long double, the result is long double.

    • Otherwise, if either is double, the result is double.

    • Otherwise, if either is float, the result is float.

    • Otherwise, the integer promotions are applied to each operand (these are specified in 6.3.1.1 2), and then the two types are converted to a common integer type. The full rules for this are somewhat complicated, use a concept of rank that requires some explanation, and cover some esoteric situations, so I will just summarize them for normal situations: If both types are int or narrower (meaning fewer bits or the same number of bits but signed instead of unsigned), the result is int. Otherwise, if both are unsigned int or narrower, the result is unsigned int. Otherwise, the result is the wider type.


    The structure, union, and void rules are clear: The two operands must have the same type, and that is the result.



    Paragraph 6 describes the result for pointers:




    If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.




    In summary, that says:




    • If either operand has qualifiers (const, volatile, restrict, or _Atomic), include those in the result type.

    • If the two types are different but compatible (such as an array of unknown size and an array of known size, both with the same type of elements), then combine the two types. (Other possibilities for combining, besides array size, include the elements of the arrays being different but compatible types, a function with and without a parameter list, and the parameters to functions being different but compatible types.)






    share|improve this answer


























    • So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

      – BellSnow
      Jan 6 at 15:08











    • @BellSnow: Yes.

      – Eric Postpischil
      Jan 6 at 15:44














    19












    19








    19







    The type of a ? b : c is not dependent on a. It is determined unconditionally by the types of b and c. The full rules are complicated, but, for arithmetic operands, the type is determined by the usual arithmetic conversions. In effect, the two operands are converted to a common type. For int and unsigned int, the resulting type is unsigned int.



    The conditional operator, ? : is described in clause 6.5.15 of the C 2018 standard. Paragraph 4 says the result is “converted to the type described below.”



    Paragraph 5 describes the result for arithmetic types, structures, and unions:




    If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.




    Arithmetic types are integer and floating-point types, per 6.2.5 18. (These include both real and complex types.) The usual arithmetic conversions are described in 6.3.1.8 1, which are (in my summary, not quoted):




    • If either is a complex type, the result is complex, and the remaining rules describe the type of the real and imaginary parts. Otherwise, the result is real, and the remaining rules describe its type.

    • If either is long double, the result is long double.

    • Otherwise, if either is double, the result is double.

    • Otherwise, if either is float, the result is float.

    • Otherwise, the integer promotions are applied to each operand (these are specified in 6.3.1.1 2), and then the two types are converted to a common integer type. The full rules for this are somewhat complicated, use a concept of rank that requires some explanation, and cover some esoteric situations, so I will just summarize them for normal situations: If both types are int or narrower (meaning fewer bits or the same number of bits but signed instead of unsigned), the result is int. Otherwise, if both are unsigned int or narrower, the result is unsigned int. Otherwise, the result is the wider type.


    The structure, union, and void rules are clear: The two operands must have the same type, and that is the result.



    Paragraph 6 describes the result for pointers:




    If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.




    In summary, that says:




    • If either operand has qualifiers (const, volatile, restrict, or _Atomic), include those in the result type.

    • If the two types are different but compatible (such as an array of unknown size and an array of known size, both with the same type of elements), then combine the two types. (Other possibilities for combining, besides array size, include the elements of the arrays being different but compatible types, a function with and without a parameter list, and the parameters to functions being different but compatible types.)






    share|improve this answer















    The type of a ? b : c is not dependent on a. It is determined unconditionally by the types of b and c. The full rules are complicated, but, for arithmetic operands, the type is determined by the usual arithmetic conversions. In effect, the two operands are converted to a common type. For int and unsigned int, the resulting type is unsigned int.



    The conditional operator, ? : is described in clause 6.5.15 of the C 2018 standard. Paragraph 4 says the result is “converted to the type described below.”



    Paragraph 5 describes the result for arithmetic types, structures, and unions:




    If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.




    Arithmetic types are integer and floating-point types, per 6.2.5 18. (These include both real and complex types.) The usual arithmetic conversions are described in 6.3.1.8 1, which are (in my summary, not quoted):




    • If either is a complex type, the result is complex, and the remaining rules describe the type of the real and imaginary parts. Otherwise, the result is real, and the remaining rules describe its type.

    • If either is long double, the result is long double.

    • Otherwise, if either is double, the result is double.

    • Otherwise, if either is float, the result is float.

    • Otherwise, the integer promotions are applied to each operand (these are specified in 6.3.1.1 2), and then the two types are converted to a common integer type. The full rules for this are somewhat complicated, use a concept of rank that requires some explanation, and cover some esoteric situations, so I will just summarize them for normal situations: If both types are int or narrower (meaning fewer bits or the same number of bits but signed instead of unsigned), the result is int. Otherwise, if both are unsigned int or narrower, the result is unsigned int. Otherwise, the result is the wider type.


    The structure, union, and void rules are clear: The two operands must have the same type, and that is the result.



    Paragraph 6 describes the result for pointers:




    If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.




    In summary, that says:




    • If either operand has qualifiers (const, volatile, restrict, or _Atomic), include those in the result type.

    • If the two types are different but compatible (such as an array of unknown size and an array of known size, both with the same type of elements), then combine the two types. (Other possibilities for combining, besides array size, include the elements of the arrays being different but compatible types, a function with and without a parameter list, and the parameters to functions being different but compatible types.)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 6 at 15:07

























    answered Jan 6 at 14:32









    Eric PostpischilEric Postpischil

    72.8k879158




    72.8k879158













    • So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

      – BellSnow
      Jan 6 at 15:08











    • @BellSnow: Yes.

      – Eric Postpischil
      Jan 6 at 15:44



















    • So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

      – BellSnow
      Jan 6 at 15:08











    • @BellSnow: Yes.

      – Eric Postpischil
      Jan 6 at 15:44

















    So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

    – BellSnow
    Jan 6 at 15:08





    So, according to your answer, is it right to understand that the result type of my code is "unsigned int" because of the sentence, "If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result." ?

    – BellSnow
    Jan 6 at 15:08













    @BellSnow: Yes.

    – Eric Postpischil
    Jan 6 at 15:44





    @BellSnow: Yes.

    – Eric Postpischil
    Jan 6 at 15:44













    2














    You should not mix signed and unsigned values unless you perfectly know what is unfolding (and you want that behavior) [checkout here why]. Behind the scenes, as you have an unsigned number in your expression, C is evaluated your greater-than operator to an unsigned integer >. Therefore, your comparison will not evaluate true as "unsigned -1" is greater than your unsigned 1.






    share|improve this answer



















    • 1





      OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

      – Eric Postpischil
      Jan 6 at 14:59











    • Indeed. I was writing in a general sense.

      – delirium
      Jan 6 at 15:01






    • 1





      Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

      – chqrlie
      Jan 6 at 15:44













    • @chqrlie exactly! That behavior is even harder to bug.

      – delirium
      Jan 7 at 10:48











    • @delirium: to bug or to debug, that is the question... :)

      – chqrlie
      Jan 7 at 13:46


















    2














    You should not mix signed and unsigned values unless you perfectly know what is unfolding (and you want that behavior) [checkout here why]. Behind the scenes, as you have an unsigned number in your expression, C is evaluated your greater-than operator to an unsigned integer >. Therefore, your comparison will not evaluate true as "unsigned -1" is greater than your unsigned 1.






    share|improve this answer



















    • 1





      OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

      – Eric Postpischil
      Jan 6 at 14:59











    • Indeed. I was writing in a general sense.

      – delirium
      Jan 6 at 15:01






    • 1





      Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

      – chqrlie
      Jan 6 at 15:44













    • @chqrlie exactly! That behavior is even harder to bug.

      – delirium
      Jan 7 at 10:48











    • @delirium: to bug or to debug, that is the question... :)

      – chqrlie
      Jan 7 at 13:46
















    2












    2








    2







    You should not mix signed and unsigned values unless you perfectly know what is unfolding (and you want that behavior) [checkout here why]. Behind the scenes, as you have an unsigned number in your expression, C is evaluated your greater-than operator to an unsigned integer >. Therefore, your comparison will not evaluate true as "unsigned -1" is greater than your unsigned 1.






    share|improve this answer













    You should not mix signed and unsigned values unless you perfectly know what is unfolding (and you want that behavior) [checkout here why]. Behind the scenes, as you have an unsigned number in your expression, C is evaluated your greater-than operator to an unsigned integer >. Therefore, your comparison will not evaluate true as "unsigned -1" is greater than your unsigned 1.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 6 at 14:38









    deliriumdelirium

    638518




    638518








    • 1





      OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

      – Eric Postpischil
      Jan 6 at 14:59











    • Indeed. I was writing in a general sense.

      – delirium
      Jan 6 at 15:01






    • 1





      Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

      – chqrlie
      Jan 6 at 15:44













    • @chqrlie exactly! That behavior is even harder to bug.

      – delirium
      Jan 7 at 10:48











    • @delirium: to bug or to debug, that is the question... :)

      – chqrlie
      Jan 7 at 13:46
















    • 1





      OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

      – Eric Postpischil
      Jan 6 at 14:59











    • Indeed. I was writing in a general sense.

      – delirium
      Jan 6 at 15:01






    • 1





      Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

      – chqrlie
      Jan 6 at 15:44













    • @chqrlie exactly! That behavior is even harder to bug.

      – delirium
      Jan 7 at 10:48











    • @delirium: to bug or to debug, that is the question... :)

      – chqrlie
      Jan 7 at 13:46










    1




    1





    OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

    – Eric Postpischil
    Jan 6 at 14:59





    OP did not think they were mixing signed and unsigned values. They believed they were getting either a signed or an unsigned value from ? :; they did not know that ? : combines the types.

    – Eric Postpischil
    Jan 6 at 14:59













    Indeed. I was writing in a general sense.

    – delirium
    Jan 6 at 15:01





    Indeed. I was writing in a general sense.

    – delirium
    Jan 6 at 15:01




    1




    1





    Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

    – chqrlie
    Jan 6 at 15:44







    Your advice is very reasonable, mixing signed and unsigned types in arithmetic expressions should be avoided because the rules are complicated and somewhat counterintuitive. As a matter of fact, having an unsigned operand may not always force an unsigned resulting type: for example ((1 ? (long)1 : (unsigned)2) > -1) may produce a different result on different platforms, depending on the respective sizes of types int and long.

    – chqrlie
    Jan 6 at 15:44















    @chqrlie exactly! That behavior is even harder to bug.

    – delirium
    Jan 7 at 10:48





    @chqrlie exactly! That behavior is even harder to bug.

    – delirium
    Jan 7 at 10:48













    @delirium: to bug or to debug, that is the question... :)

    – chqrlie
    Jan 7 at 13:46







    @delirium: to bug or to debug, that is the question... :)

    – chqrlie
    Jan 7 at 13:46













    1














    The result of your ?: operator has unsigned type, since it is the common type for int and unsigned (your 2nd and 3rd operands). The result has the "expected" value of 1, but its type is unsigned.



    The rest has nothing to do with ?: at all. It is well-described in numerous answers for this frequently asked question: Comparison operation on unsigned and signed integers






    share|improve this answer






























      1














      The result of your ?: operator has unsigned type, since it is the common type for int and unsigned (your 2nd and 3rd operands). The result has the "expected" value of 1, but its type is unsigned.



      The rest has nothing to do with ?: at all. It is well-described in numerous answers for this frequently asked question: Comparison operation on unsigned and signed integers






      share|improve this answer




























        1












        1








        1







        The result of your ?: operator has unsigned type, since it is the common type for int and unsigned (your 2nd and 3rd operands). The result has the "expected" value of 1, but its type is unsigned.



        The rest has nothing to do with ?: at all. It is well-described in numerous answers for this frequently asked question: Comparison operation on unsigned and signed integers






        share|improve this answer















        The result of your ?: operator has unsigned type, since it is the common type for int and unsigned (your 2nd and 3rd operands). The result has the "expected" value of 1, but its type is unsigned.



        The rest has nothing to do with ?: at all. It is well-described in numerous answers for this frequently asked question: Comparison operation on unsigned and signed integers







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 7 at 4:18

























        answered Jan 7 at 3:21









        AnTAnT

        258k32414657




        258k32414657























            0














            Just to put a number on it, if I drop this code:



            unsigned x = (unsigned)-1;


            into a program I'm debugging right now, X has the value 4294967295 (UINT_MAX), i.e. your program "sees" the comparison as something like this:



            ((1 ? (int)1 : (unsigned int)2) > 4294967296)


            (Would have entered this as a comment, but I don't have the reputation.)






            share|improve this answer
























            • just use -1U or 2U instead of (unsigned)-1;...

              – phuclv
              Jan 7 at 1:26






            • 1





              This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

              – M.M
              Jan 7 at 4:19
















            0














            Just to put a number on it, if I drop this code:



            unsigned x = (unsigned)-1;


            into a program I'm debugging right now, X has the value 4294967295 (UINT_MAX), i.e. your program "sees" the comparison as something like this:



            ((1 ? (int)1 : (unsigned int)2) > 4294967296)


            (Would have entered this as a comment, but I don't have the reputation.)






            share|improve this answer
























            • just use -1U or 2U instead of (unsigned)-1;...

              – phuclv
              Jan 7 at 1:26






            • 1





              This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

              – M.M
              Jan 7 at 4:19














            0












            0








            0







            Just to put a number on it, if I drop this code:



            unsigned x = (unsigned)-1;


            into a program I'm debugging right now, X has the value 4294967295 (UINT_MAX), i.e. your program "sees" the comparison as something like this:



            ((1 ? (int)1 : (unsigned int)2) > 4294967296)


            (Would have entered this as a comment, but I don't have the reputation.)






            share|improve this answer













            Just to put a number on it, if I drop this code:



            unsigned x = (unsigned)-1;


            into a program I'm debugging right now, X has the value 4294967295 (UINT_MAX), i.e. your program "sees" the comparison as something like this:



            ((1 ? (int)1 : (unsigned int)2) > 4294967296)


            (Would have entered this as a comment, but I don't have the reputation.)







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 6 at 18:05









            Bob CramBob Cram

            495




            495













            • just use -1U or 2U instead of (unsigned)-1;...

              – phuclv
              Jan 7 at 1:26






            • 1





              This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

              – M.M
              Jan 7 at 4:19



















            • just use -1U or 2U instead of (unsigned)-1;...

              – phuclv
              Jan 7 at 1:26






            • 1





              This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

              – M.M
              Jan 7 at 4:19

















            just use -1U or 2U instead of (unsigned)-1;...

            – phuclv
            Jan 7 at 1:26





            just use -1U or 2U instead of (unsigned)-1;...

            – phuclv
            Jan 7 at 1:26




            1




            1





            This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

            – M.M
            Jan 7 at 4:19





            This is incorrect, 4294967296 has type long long (on common systems) . Maybe you meant to write 4294967295 there? (But if so, add the u suffix)

            – M.M
            Jan 7 at 4:19


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54062382%2fwhat-is-happening-in-i-have-no-idea-about-the-return-type%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How do I know what Microsoft account the skydrive app is syncing to?

            Grease: Live!

            When does type information flow backwards in C++?