{"id":7014,"date":"2014-08-04T10:55:07","date_gmt":"2014-08-04T09:55:07","guid":{"rendered":"https:\/\/blogs.mentor.com\/colinwalls\/?p=7014"},"modified":"2026-03-26T16:43:57","modified_gmt":"2026-03-26T20:43:57","slug":"undefined-behavior-and-other-delights-of-bad-c-programming","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/embedded-software\/2014\/08\/04\/undefined-behavior-and-other-delights-of-bad-c-programming\/","title":{"rendered":"Undefined behavior and other delights of (bad) C programming"},"content":{"rendered":"<p>I started a couple of weeks ago, when I received an email from <a href=\"http:\/\/aesics.ahduni.edu.in\/faculty_sandeep_vasant.shtml\" target=\"_blank\" rel=\"noopener noreferrer\">Sandeep Vasant<\/a> from Ahmedabad University in India. For reasons that he has yet to reveal, he was having trouble with some code like this:<\/p>\n<pre>int a=10, b=20, c=0;\nc = a++ + a++ + b++ + b++ + ++a + ++b;\n\n<\/pre>\n<p>He tried this with one compiler and the resulting values of <strong>a<\/strong>, <strong>b<\/strong> and <strong>c<\/strong> were 13, 23 and 96 respectively. He was satisfied with this result. Then he tried a different compiler, which yielded a final value for <strong>c<\/strong> of 98, which he found confusing.<\/p>\n<p>I started looking into this, certain that the explanation was simple &#8230;<!--more--><\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2014\/07\/359f538e69461c8de26e816c3f981dd7.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-7006\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2014\/07\/359f538e69461c8de26e816c3f981dd7.png\" alt=\"359f538e69461c8de26e816c3f981dd7\" width=\"409\" height=\"300\" \/><\/a>As I work for a company that sell <a href=\"http:\/\/www.mentor.com\/embedded-software\/sourcery-tools\/sourcery-codebench\/overview\" target=\"_blank\" rel=\"noopener noreferrer\">embedded software development tools<\/a>, I have a natural interest in programming languages and their quirks &#8211; even if the code is not specifically embedded. I believe that embedded developers are often more interested in what is going on &#8220;behind the scenes&#8221; than their desktop computer software development counterparts.<\/p>\n<p>My first thought was that, although the precedence of the <strong>+<\/strong> and <strong>++<\/strong> operators is clear and the functionality of the pre-increment and post-increment versions of <strong>++<\/strong> is unambiguous, the order of evaluation of the the operators is not defined. Maybe they are evaluated left to right or perhaps right to left. So, instead of using a compiler, I decided to work it out by hand. Going left to right, I got 10 + 11 + 20 + 21 + 13 + 23 = 98; going the other way, I got 21 + 11 + 21 + 22 + 11 + 12 = 98. So it made no difference. In both cases I got the result that Sandeep had been confused by.<\/p>\n<p>Now it was time to try a compiler [I used CodePad]. I wrote this:<\/p>\n<pre>int a, b, c;<\/pre>\n<pre>a=10, b=20, c=0; \/\/ original code\nc = a++ + a++ + b++ + b++ + ++a + ++b;\nprintf(\"%d %d %d\\n\", a, b, c);<\/pre>\n<pre>a=10, b=20, c=0; \/\/ sequence of sub-expressions reversed\nc = ++b + ++a + b++ + b++ + a++ + a++;\nprintf(\"%d %d %d\\n\", a, b, c);\n\n<\/pre>\n<p>The results were:<br \/>\n13 23 92<br \/>\n13 23 96<\/p>\n<p>Now I was confused, as neither result seemed correct. I rewrote the code:<\/p>\n<pre>a=10, b=20, c=0; \/\/ explicit left to right evaluation\nc = a++;\nc += a++;\nc += b++;\nc += b++;\nc += ++a;\nc += ++b;\nprintf(\"%d %d %d\\n\", a, b, c);<\/pre>\n<pre>a=10, b=20, c=0; \/\/ explicit right to left evaluation\nc = ++b;\nc += ++a;\nc += b++;\nc += b++;\nc += a++;\nc += a++;\nprintf(\"%d %d %d\\n\", a, b, c);\n\n<\/pre>\n<p>I was much happier with the results this time:<br \/>\n13 23 98<br \/>\n13 23 98<\/p>\n<p>So what is happening here? I consulted my colleague <a href=\"mailto:jonathan@codesourcery.com\" target=\"_blank\" rel=\"noopener noreferrer\">Jon Roelofs<\/a>, who provided a straightforward explanation: The order of evaluation is unspecified &#8211; it could be right to left or left to right, but it could also be any other order that the compiler felt was appropriate. When side effects of the evaluations of sub-expressions occur [like the increment operators], there are undefined results. Needless, coding an algorithm which has an undefined result is rather pointless. Some compilers would give a warning\/error in this situation.<\/p>\n<p>Undefined behavior only happens when there is reading and writing to variables on the right hand side on an assignment more than once. For example:<\/p>\n<pre>a = b++ + c++ + d++;\n\n<\/pre>\n<p>does not exhibit undefined behavior.<\/p>\n<p>Out of interest Jon suggested that I try this code:<\/p>\n<pre>int foo()\n{\n printf(\"foo\\n\");\n return 0;\n}<\/pre>\n<pre>int bar()\n{\n printf(\"bar\\n\");\n return 1;\n}<\/pre>\n<pre>int baz()\n{\n printf(\"baz\\n\");\n return 2;\n}<\/pre>\n<pre>void main()\n{\n printf(\"%d %d %d\\n\", foo(), bar(), baz());\n}\n\n<\/pre>\n<p>The result I got was unsurprising:<br \/>\nbaz<br \/>\nbar<br \/>\nfoo<br \/>\n0 1 2<\/p>\n<p>He pointed out that the three lines of text could have come out in any order; the numeric data will always be displayed last and in the correct order.<\/p>\n<p>There are numerous examples of this kind of challenge. Again, Jon suggested that I try this:<\/p>\n<pre>c = a+++b;\n\n<\/pre>\n<p>Is this treated as <strong>c = a++ + b;<\/strong> or <strong>c = a + ++b;<\/strong> ? It must be the former. Even though it looks as if it could have gone either way, the C language standard nails it. So this is not undefined behavior.<\/p>\n<p>Without wishing to sound superior, I think that it would be very unlikely that I would encounter this problem in &#8220;real&#8221; code that I had written. This is because, as I started out writing assembly language, I am naturally inclined to keep my statements in C very simple and, hence, do not introduce such complexity.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I started a couple of weeks ago, when I received an email from Sandeep Vasant from Ahmedabad University in India&#8230;.<\/p>\n","protected":false},"author":71677,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1],"tags":[313,300,340,478],"industry":[],"product":[],"coauthors":[],"class_list":["post-7014","post","type-post","status-publish","format-standard","hentry","category-news","tag-c","tag-embedded-software","tag-programming-languages","tag-sourcery-codebench"],"_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts\/7014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/users\/71677"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/comments?post=7014"}],"version-history":[{"count":1,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts\/7014\/revisions"}],"predecessor-version":[{"id":10292,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts\/7014\/revisions\/10292"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/media?parent=7014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/categories?post=7014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/tags?post=7014"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/industry?post=7014"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/product?post=7014"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/coauthors?post=7014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}