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












17














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









New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 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
















17














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









New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 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














17












17








17


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









New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











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









New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 2 days ago









Deduplicator

34.1k64787




34.1k64787






New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Jan 6 at 14:15









BellSnowBellSnow

945




945




New contributor




BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






BellSnow is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 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


















18














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
    2 days ago










  • @delirium: to bug or to debug, that is the question... :)
    – chqrlie
    2 days ago





















1














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








New contributor




Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • just use -1U or 2U instead of (unsigned)-1;...
    – phuclv
    2 days ago






  • 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
    2 days ago



















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























    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
    });


    }
    });






    BellSnow is a new contributor. Be nice, and check out our Code of Conduct.










    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









    18














    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
















    18














    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














    18












    18








    18






    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.1k878158




    72.1k878158












    • 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
      2 days ago










    • @delirium: to bug or to debug, that is the question... :)
      – chqrlie
      2 days ago


















    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
      2 days ago










    • @delirium: to bug or to debug, that is the question... :)
      – chqrlie
      2 days ago
















    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

    607418




    607418








    • 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
      2 days ago










    • @delirium: to bug or to debug, that is the question... :)
      – chqrlie
      2 days ago
















    • 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
      2 days ago










    • @delirium: to bug or to debug, that is the question... :)
      – chqrlie
      2 days ago










    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
    2 days ago




    @chqrlie exactly! That behavior is even harder to bug.
    – delirium
    2 days ago












    @delirium: to bug or to debug, that is the question... :)
    – chqrlie
    2 days ago






    @delirium: to bug or to debug, that is the question... :)
    – chqrlie
    2 days ago













    1














    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








    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















    • just use -1U or 2U instead of (unsigned)-1;...
      – phuclv
      2 days ago






    • 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
      2 days ago
















    1














    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








    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















    • just use -1U or 2U instead of (unsigned)-1;...
      – phuclv
      2 days ago






    • 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
      2 days ago














    1












    1








    1






    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








    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    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








    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    share|improve this answer



    share|improve this answer






    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    answered 2 days ago









    Bob CramBob Cram

    595




    595




    New contributor




    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





    New contributor





    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    Bob Cram is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.












    • just use -1U or 2U instead of (unsigned)-1;...
      – phuclv
      2 days ago






    • 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
      2 days ago


















    • just use -1U or 2U instead of (unsigned)-1;...
      – phuclv
      2 days ago






    • 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
      2 days ago
















    just use -1U or 2U instead of (unsigned)-1;...
    – phuclv
    2 days ago




    just use -1U or 2U instead of (unsigned)-1;...
    – phuclv
    2 days ago




    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
    2 days ago




    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
    2 days ago











    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 2 days ago

























        answered 2 days ago









        AnTAnT

        257k32411655




        257k32411655






















            BellSnow is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            BellSnow is a new contributor. Be nice, and check out our Code of Conduct.













            BellSnow is a new contributor. Be nice, and check out our Code of Conduct.












            BellSnow is a new contributor. Be nice, and check out our Code of Conduct.
















            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            RAC Tourist Trophy