Does the statement `int val = (++i > ++j) ? ++i : ++j;` invoke undefined behavior?2019 Community Moderator Electionsequence points in cWhy are these constructs using pre and post-increment undefined behavior?Undefined, unspecified and implementation-defined behaviorIn C is there any guarantee with code prior to undefined behavior?Undefined behavior and sequence pointsUndefined behavior and sequence points reloadedIs the behavior of i = post_increment_i() specified, unspecified, or undefined?Undefined behavior and sequence pointUndefined behavior with: c = (b=a+2) - (a=1) ;Does a[a[0]] = 1 produce undefined behavior?printf with consecutive function as argument, undefined behavior

How could an airship be repaired midflight?

Russian cases: A few examples, I'm really confused

Recruiter wants very extensive technical details about all of my previous work

Is "upgrade" the right word to use in this context?

Did Ender ever learn that he killed Stilson and/or Bonzo?

Why Choose Less Effective Armour Types?

What is the adequate fee for a reveal operation?

How to use deus ex machina safely?

Is it insecure to send a password in a `curl` command?

What did Alexander Pope mean by "Expletives their feeble Aid do join"?

Tikz diagrams and node placements

Life insurance that covers only simultaneous/dual deaths

Sailing the cryptic seas

how to draw this figure in latex

My adviser wants to be the first author

Pauli exclusion principle

Was Shankara a bhakta of Saguna Brahman Narayana or did he consider Nirguna Brahman to be supreme?

Is it possible to upcast ritual spells?

What do you call the act of removing a part of a word and replacing it with an apostrophe

How do I parse a string to number while destructuring?

Welcoming 2019 Pi day: How to draw the letter π?

Employee lack of ownership

Violin - Can double stops be played when the strings are not next to each other?

Print a physical multiplication table



Does the statement `int val = (++i > ++j) ? ++i : ++j;` invoke undefined behavior?



2019 Community Moderator Electionsequence points in cWhy are these constructs using pre and post-increment undefined behavior?Undefined, unspecified and implementation-defined behaviorIn C is there any guarantee with code prior to undefined behavior?Undefined behavior and sequence pointsUndefined behavior and sequence points reloadedIs the behavior of i = post_increment_i() specified, unspecified, or undefined?Undefined behavior and sequence pointUndefined behavior with: c = (b=a+2) - (a=1) ;Does a[a[0]] = 1 produce undefined behavior?printf with consecutive function as argument, undefined behavior










21















Given the following program:



#include <stdio.h>
int main(void)

int i = 1, j = 2;
int val = (++i > ++j) ? ++i : ++j;
printf("%dn", val); // prints 4
return 0;



The initialization of val seems like it could be hiding some undefined behavior, but I don't see any point at which an object is either modified more than once or modified and used without a sequence point in between. Could someone
either correct or corroborate me on this?










share|improve this question



















  • 5





    Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

    – Weather Vane
    yesterday






  • 1





    You got 4. What did you expect?

    – Bob Jarvis
    yesterday











  • I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

    – max1000001
    yesterday











  • the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

    – Jean-François Fabre
    yesterday






  • 5





    @Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

    – sepp2k
    yesterday















21















Given the following program:



#include <stdio.h>
int main(void)

int i = 1, j = 2;
int val = (++i > ++j) ? ++i : ++j;
printf("%dn", val); // prints 4
return 0;



The initialization of val seems like it could be hiding some undefined behavior, but I don't see any point at which an object is either modified more than once or modified and used without a sequence point in between. Could someone
either correct or corroborate me on this?










share|improve this question



















  • 5





    Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

    – Weather Vane
    yesterday






  • 1





    You got 4. What did you expect?

    – Bob Jarvis
    yesterday











  • I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

    – max1000001
    yesterday











  • the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

    – Jean-François Fabre
    yesterday






  • 5





    @Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

    – sepp2k
    yesterday













21












21








21


1






Given the following program:



#include <stdio.h>
int main(void)

int i = 1, j = 2;
int val = (++i > ++j) ? ++i : ++j;
printf("%dn", val); // prints 4
return 0;



The initialization of val seems like it could be hiding some undefined behavior, but I don't see any point at which an object is either modified more than once or modified and used without a sequence point in between. Could someone
either correct or corroborate me on this?










share|improve this question
















Given the following program:



#include <stdio.h>
int main(void)

int i = 1, j = 2;
int val = (++i > ++j) ? ++i : ++j;
printf("%dn", val); // prints 4
return 0;



The initialization of val seems like it could be hiding some undefined behavior, but I don't see any point at which an object is either modified more than once or modified and used without a sequence point in between. Could someone
either correct or corroborate me on this?







c ternary-operator sequence-points






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









machine_1

2,47921332




2,47921332










asked yesterday









max1000001max1000001

16311




16311







  • 5





    Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

    – Weather Vane
    yesterday






  • 1





    You got 4. What did you expect?

    – Bob Jarvis
    yesterday











  • I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

    – max1000001
    yesterday











  • the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

    – Jean-François Fabre
    yesterday






  • 5





    @Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

    – sepp2k
    yesterday












  • 5





    Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

    – Weather Vane
    yesterday






  • 1





    You got 4. What did you expect?

    – Bob Jarvis
    yesterday











  • I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

    – max1000001
    yesterday











  • the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

    – Jean-François Fabre
    yesterday






  • 5





    @Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

    – sepp2k
    yesterday







5




5





Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

– Weather Vane
yesterday





Is there a sequence point? Please see this answer which states there is one "Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated (6.5.15)."

– Weather Vane
yesterday




1




1





You got 4. What did you expect?

– Bob Jarvis
yesterday





You got 4. What did you expect?

– Bob Jarvis
yesterday













I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

– max1000001
yesterday





I expected 4. I don't think this code invokes UB, but I was told on another question that it does. Just wanted to eliminate any confusion as to whether that specific statement causes UB, and maybe get a better explanation that the one I provided in the question.

– max1000001
yesterday













the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

– Jean-François Fabre
yesterday





the ternary expression guarantees the sequence point. I cannot find any reference to (++i > ++j) though. Is > a sequence point?

– Jean-François Fabre
yesterday




5




5





@Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

– sepp2k
yesterday





@Jean-FrançoisFabre No, but it doesn't need to be. There's no need for a sequence point between two changes of two different variables. ++i > ++i would be UB though.

– sepp2k
yesterday












4 Answers
4






active

oldest

votes


















33














The behavior of this code is well defined.



The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:




The first operand is evaluated; there is a sequence point
between its evaluation and the evaluation of the second or third
operand (whichever is evaluated). The second operand is evaluated
only if the first compares unequal to 0; the third operand is
evaluated only if the first compares equal to 0; the result is
the value of the second or third operand (whichever is
evaluated), converted to the type described below.




In the case of your expression:



int val = (++i > ++j) ? ++i : ++j;


++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.






share|improve this answer


















  • 3





    Thank you for your detailed and direct answer!

    – max1000001
    yesterday


















6














too late, but maybe useful.



(++i > ++j) ? ++i : ++j;


In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point




Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated




In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.



In your expression the only conflict that could appear would be between the first and second ++i or ++j.



At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).



Quote from 5.1.2.3p3 Program execution




The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.




When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.



For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences



i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.






share|improve this answer

























  • I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

    – max1000001
    yesterday


















5














There may be no UB in your program, but in the question:
Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?



The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.



Of course this doesn't happen in your full example because you've specified the values as small integers.






share|improve this answer


















  • 2





    I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

    – machine_1
    yesterday






  • 2





    The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

    – eckes
    yesterday











  • @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

    – Holger
    yesterday











  • Was going to complain, but on a second thought +1 :)

    – Damon
    yesterday


















0














I was going to comment on @Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!



On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:



The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.



Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.



So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).



Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.



The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.

Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.



Try and debug that.






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



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55170504%2fdoes-the-statement-int-val-i-j-i-j-invoke-undefined-behavio%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









    33














    The behavior of this code is well defined.



    The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:




    The first operand is evaluated; there is a sequence point
    between its evaluation and the evaluation of the second or third
    operand (whichever is evaluated). The second operand is evaluated
    only if the first compares unequal to 0; the third operand is
    evaluated only if the first compares equal to 0; the result is
    the value of the second or third operand (whichever is
    evaluated), converted to the type described below.




    In the case of your expression:



    int val = (++i > ++j) ? ++i : ++j;


    ++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.






    share|improve this answer


















    • 3





      Thank you for your detailed and direct answer!

      – max1000001
      yesterday















    33














    The behavior of this code is well defined.



    The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:




    The first operand is evaluated; there is a sequence point
    between its evaluation and the evaluation of the second or third
    operand (whichever is evaluated). The second operand is evaluated
    only if the first compares unequal to 0; the third operand is
    evaluated only if the first compares equal to 0; the result is
    the value of the second or third operand (whichever is
    evaluated), converted to the type described below.




    In the case of your expression:



    int val = (++i > ++j) ? ++i : ++j;


    ++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.






    share|improve this answer


















    • 3





      Thank you for your detailed and direct answer!

      – max1000001
      yesterday













    33












    33








    33







    The behavior of this code is well defined.



    The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:




    The first operand is evaluated; there is a sequence point
    between its evaluation and the evaluation of the second or third
    operand (whichever is evaluated). The second operand is evaluated
    only if the first compares unequal to 0; the third operand is
    evaluated only if the first compares equal to 0; the result is
    the value of the second or third operand (whichever is
    evaluated), converted to the type described below.




    In the case of your expression:



    int val = (++i > ++j) ? ++i : ++j;


    ++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.






    share|improve this answer













    The behavior of this code is well defined.



    The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:




    The first operand is evaluated; there is a sequence point
    between its evaluation and the evaluation of the second or third
    operand (whichever is evaluated). The second operand is evaluated
    only if the first compares unequal to 0; the third operand is
    evaluated only if the first compares equal to 0; the result is
    the value of the second or third operand (whichever is
    evaluated), converted to the type described below.




    In the case of your expression:



    int val = (++i > ++j) ? ++i : ++j;


    ++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    dbushdbush

    102k13108144




    102k13108144







    • 3





      Thank you for your detailed and direct answer!

      – max1000001
      yesterday












    • 3





      Thank you for your detailed and direct answer!

      – max1000001
      yesterday







    3




    3





    Thank you for your detailed and direct answer!

    – max1000001
    yesterday





    Thank you for your detailed and direct answer!

    – max1000001
    yesterday













    6














    too late, but maybe useful.



    (++i > ++j) ? ++i : ++j;


    In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point




    Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated




    In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.



    In your expression the only conflict that could appear would be between the first and second ++i or ++j.



    At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).



    Quote from 5.1.2.3p3 Program execution




    The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.




    When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.



    For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences



    i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.






    share|improve this answer

























    • I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

      – max1000001
      yesterday















    6














    too late, but maybe useful.



    (++i > ++j) ? ++i : ++j;


    In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point




    Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated




    In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.



    In your expression the only conflict that could appear would be between the first and second ++i or ++j.



    At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).



    Quote from 5.1.2.3p3 Program execution




    The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.




    When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.



    For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences



    i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.






    share|improve this answer

























    • I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

      – max1000001
      yesterday













    6












    6








    6







    too late, but maybe useful.



    (++i > ++j) ? ++i : ++j;


    In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point




    Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated




    In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.



    In your expression the only conflict that could appear would be between the first and second ++i or ++j.



    At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).



    Quote from 5.1.2.3p3 Program execution




    The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.




    When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.



    For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences



    i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.






    share|improve this answer















    too late, but maybe useful.



    (++i > ++j) ? ++i : ++j;


    In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point




    Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated




    In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.



    In your expression the only conflict that could appear would be between the first and second ++i or ++j.



    At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).



    Quote from 5.1.2.3p3 Program execution




    The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.




    When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.



    For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences



    i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    alinsoaralinsoar

    8,91013352




    8,91013352












    • I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

      – max1000001
      yesterday

















    • I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

      – max1000001
      yesterday
















    I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

    – max1000001
    yesterday





    I think the part where you enumerate the modifications to i and j as "possible conflicts" adds something new and useful to the analysis. I hadn't thought of that, thanks!

    – max1000001
    yesterday











    5














    There may be no UB in your program, but in the question:
    Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?



    The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.



    Of course this doesn't happen in your full example because you've specified the values as small integers.






    share|improve this answer


















    • 2





      I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

      – machine_1
      yesterday






    • 2





      The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

      – eckes
      yesterday











    • @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

      – Holger
      yesterday











    • Was going to complain, but on a second thought +1 :)

      – Damon
      yesterday















    5














    There may be no UB in your program, but in the question:
    Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?



    The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.



    Of course this doesn't happen in your full example because you've specified the values as small integers.






    share|improve this answer


















    • 2





      I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

      – machine_1
      yesterday






    • 2





      The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

      – eckes
      yesterday











    • @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

      – Holger
      yesterday











    • Was going to complain, but on a second thought +1 :)

      – Damon
      yesterday













    5












    5








    5







    There may be no UB in your program, but in the question:
    Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?



    The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.



    Of course this doesn't happen in your full example because you've specified the values as small integers.






    share|improve this answer













    There may be no UB in your program, but in the question:
    Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?



    The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.



    Of course this doesn't happen in your full example because you've specified the values as small integers.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Doug CurrieDoug Currie

    35.9k78109




    35.9k78109







    • 2





      I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

      – machine_1
      yesterday






    • 2





      The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

      – eckes
      yesterday











    • @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

      – Holger
      yesterday











    • Was going to complain, but on a second thought +1 :)

      – Damon
      yesterday












    • 2





      I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

      – machine_1
      yesterday






    • 2





      The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

      – eckes
      yesterday











    • @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

      – Holger
      yesterday











    • Was going to complain, but on a second thought +1 :)

      – Damon
      yesterday







    2




    2





    I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

    – machine_1
    yesterday





    I assure you that the question is not about signed integer overflow. It's about whether there is a sequence point between the first operand of the ternary operator and whichever wins from the second and the third operands.

    – machine_1
    yesterday




    2




    2





    The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

    – eckes
    yesterday





    The question was about „some undefined behavior“ and reminders about data types beeing implementation specific are totally appropriate for such an open question. And a signed integer Flow is UB.

    – eckes
    yesterday













    @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

    – Holger
    yesterday





    @eckes but the question was “Does the …”, so an unconditional “yes” is a wrong answer. If the question was “Can the …” or “May the …”, the answer would be correct.

    – Holger
    yesterday













    Was going to complain, but on a second thought +1 :)

    – Damon
    yesterday





    Was going to complain, but on a second thought +1 :)

    – Damon
    yesterday











    0














    I was going to comment on @Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!



    On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:



    The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.



    Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.



    So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).



    Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.



    The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.

    Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.



    Try and debug that.






    share|improve this answer



























      0














      I was going to comment on @Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!



      On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:



      The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.



      Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.



      So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).



      Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.



      The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.

      Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.



      Try and debug that.






      share|improve this answer

























        0












        0








        0







        I was going to comment on @Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!



        On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:



        The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.



        Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.



        So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).



        Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.



        The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.

        Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.



        Try and debug that.






        share|improve this answer













        I was going to comment on @Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!



        On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:



        The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.



        Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.



        So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).



        Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.



        The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.

        Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.



        Try and debug that.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        DamonDamon

        52.2k15103158




        52.2k15103158



























            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%2f55170504%2fdoes-the-statement-int-val-i-j-i-j-invoke-undefined-behavio%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

            Is flight data recorder erased after every flight?When are black boxes used?What protects the location beacon (pinger) of a flight data recorder?Is there anywhere I can pick up raw flight data recorder information?Who legally owns the Flight Data Recorder?Constructing flight recorder dataWhy are FDRs and CVRs still two separate physical devices?What are the data elements shown on the GE235 flight data recorder (FDR) plot?Are CVR and FDR reset after every flight?What is the format of data stored by a Flight Data Recorder?How much data is stored in the flight data recorder per hour in a typical flight of an A380?Is a smart flight data recorder possible?

            Which is better: GPT or RelGAN for text generation?2019 Community Moderator ElectionWhat is the difference between TextGAN and LM for text generation?GANs (generative adversarial networks) possible for text as well?Generator loss not decreasing- text to image synthesisChoosing a right algorithm for template-based text generationHow should I format input and output for text generation with LSTMsGumbel Softmax vs Vanilla Softmax for GAN trainingWhich neural network to choose for classification from text/speech?NLP text autoencoder that generates text in poetic meterWhat is the interpretation of the expectation notation in the GAN formulation?What is the difference between TextGAN and LM for text generation?How to prepare the data for text generation task

            Is there a general name for the setup in which payoffs are not known exactly but players try to influence each other's perception of the payoffs?Osborne, Nash equilibria and the correctness of beliefsIs there a name for this family of games (Binomial games?)?Perfect Bayesian EquilibriumCalculating mixed strategy equilibrium in battle of sexesPure Strategy SPNEIs there a commitment mechanism which allows players to achieve pareto optimal solutions?Extensive Form GamesAn $n$-player prisoner's dilemma where a coalition of 2 players is better off defectingTit-For-Stat Strategy Best RepliesPotential solutions of the $n$-player Prisoner's Dilemma