{"id":753,"date":"2019-04-13T14:56:00","date_gmt":"2019-04-13T13:56:00","guid":{"rendered":"http:\/\/coding.moris.org\/?p=753"},"modified":"2025-10-17T23:20:08","modified_gmt":"2025-10-17T22:20:08","slug":"undefined-behaviours-in-c","status":"publish","type":"post","link":"https:\/\/priscimon.net\/coding\/2019\/04\/13\/undefined-behaviours-in-c\/","title":{"rendered":"Undefined behaviours in C"},"content":{"rendered":"\n<p><em>Undefined behaviours<\/em> in the C language confuse many beginners. As an occasional C programmer I am also baffled by them\u2014as happened with this code written as part of an Arduino sketch.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">static void\nget_input(String prompt, void* const input, void (*parse_func)(void* const), int (*validate_func)(const void* const))\n{\n  while (!validate_func((const void* const)input)) {\n    Serial.println(prompt);\n    while (Serial.available() == 0);\n    parse_func(input);\n  }\n}\n\nvoid\nloop()\n{\n  get_input(\"Enter the number of blinks: \",\n        &amp;(led-&gt;blinks),\n        *parse_int,\n        *validate_positive_int);\n}<\/pre>\n\n\n\n<p><code>get_input()<\/code> is a generic function. It takes a parameter <code>String prompt<\/code> and two function pointer parameters <code>(*parse_func)(void* const)<\/code> and <code>(*validate_func)(const void* const)<\/code>. These generic function pointers take parameters of type <code>void<\/code>, which can be cast to any other type.<\/p>\n\n\n\n<p>At runtime I passed the function <code>validate_positive_int()<\/code> as argument for parameter <code>(*validate_func)(const void* const)<\/code>. It converts its argument to an integer value and tests if the result is greater than zero.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">static int\nvalidate_positive_int(const void* const val)\n{\n  return *(const int* const)val &gt; 0;\n}<\/pre>\n\n\n\n<p>As I was debugging the sketch, I modified the function as follows<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">static int\nvalidate_positive_int(const void* const val)\n{\n  *(int*)val = 1234; \/\/ &lt;--- modification \n  return *(const int* const)val &gt; 0;\n}<\/pre>\n\n\n\n<p>Although I assigned a new value to the parameter of type <code>const void* const<\/code> \u2013 that is, a constant \u2013 the code compiled successfully, and the program executed without any error.<\/p>\n\n\n\n<p>But when I tried to change the value of the parameter by casting it to the same type as declared for the parameter, the compiler reported an error as it should.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">static int\nvalidate_positive_int(const void* const val)\n{\n  *(const int* const)val = 1234; \/\/ &lt;--- modification \n  return *(const int* const)val &gt; 0;\n}<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">test.c: In function 'validate_positive_int':<br \/>test.c:15:28: error: assignment of read-only location *(const int *)val<br \/>     *(const int* const)val = 1234;<\/pre>\n\n\n\n<p>This was puzzling because I expected the code to not compile in both cases.<\/p>\n\n\n\n<p>Going through the C documentation, I found that an undefined behaviour arises when a const object (that is, <code>const void* const<\/code>) is modified through a non-const pointer (that is, <code>int*<\/code>).<\/p>\n\n\n\n<p>Even if I was reluctant to accept this explanation because of my familiarity with compilers for safer languages that enforce parameter declarations strictly \u2013 in a case similar to the above, that the value of a const parameter is immutable \u2013 I eventually had to accept that C is different in how a parameter declaration is not enough to cause a compilation error when an argument is treated contradictorily to the declaration.<\/p>\n\n\n\n<p>Takeaway #1: When a programmer declares a parameter for a function, they ask future users of that function to call it with arguments of the declared type. However, they do not guarantee that their function will not abuse the argument. In the example above, although the function tells the caller that it must be passed a const, it was still allowed to modify the argument.<\/p>\n\n\n\n<p>Takeaway #2: As a responsible programmer, do not break the promise made to the caller in the function declaration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Undefined behaviours in the C language confuse many beginners. As an occasional C programmer I am also baffled by them\u2014as happened with this code written as part of an Arduino sketch. static void get_input(String prompt, void* const input, void (*parse_func)(void* const), int (*validate_func)(const void* const)) { while (!validate_func((const void* const)input)) { Serial.println(prompt); while (Serial.available() == [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-753","post","type-post","status-publish","format-standard","hentry","category-general"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3I4g9-c9","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/753","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/comments?post=753"}],"version-history":[{"count":43,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/753\/revisions"}],"predecessor-version":[{"id":1969,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/753\/revisions\/1969"}],"wp:attachment":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/media?parent=753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/categories?post=753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/tags?post=753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}