{"id":136,"date":"2009-03-27T01:34:44","date_gmt":"2009-03-27T09:34:44","guid":{"rendered":"\/?p=136"},"modified":"2012-11-17T03:45:54","modified_gmt":"2012-11-17T11:45:54","slug":"yet-more-dangers-of-macros-in-c","status":"publish","type":"post","link":"https:\/\/www.slimjimmy.com\/weblog\/archives\/2009\/03\/27\/yet-more-dangers-of-macros-in-c\/","title":{"rendered":"Yet more dangers of macros in C++"},"content":{"rendered":"<p>I saw some code:<\/p>\n<pre class=\"example\">\r\nstd::string s = foo();\r\nbar(s.c_str());\r\n<\/pre>\n<p>I tried changing it to:<\/p>\n<pre class=\"example\">\r\nbar(foo().c_str());\r\n<\/pre>\n<p>and things broke.  It turns out that <code>bar()<\/code> was a macro that expanded to:<\/p>\n<pre class=\"example\">\r\n#define bar(s) do { struct st; st.someString = (s); baz(&st); } while (0)\r\n<\/pre>\n<p>(If you&#8217;re wondering about the <code>do ... while (0)<\/code>, consult the <a href=\"http:\/\/c-faq.com\/cpp\/multistmt.html\" class=\"unemphasized\">comp.lang.c FAQ<\/a>.)<\/p>\n<p>This is fine for C code, but in the C++ world, this is dangerous.  In this case, <code>foo()<\/code> returns an anonymous <code>std::string<\/code> object by value.  That anonymous object then is destroyed after its internals are assigned to <code>st.someString<\/code> but before <code>baz()<\/code> gets to use it, causing <code>baz()<\/code> to be called with garbage.<\/p>\n<p>Moral #1: Macros that don&#8217;t have <em>perfect<\/em> function-like semantics shouldn&#8217;t look like functions.  For example, <strong>macros should be clearly indicated by naming them in all uppercase<\/strong>.<\/p>\n<p>Moral #2: <strong>Use inline functions when possible.<\/strong> (In this case, however, the macro was provided by a C library.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I saw some code: std::string s = foo(); bar(s.c_str()); I tried changing it to: bar(foo().c_str()); and things broke. It turns out that bar() was a macro that expanded to: #define bar(s) do { struct st; st.someString = (s); baz(&#038;st); } while (0) (If you&#8217;re wondering about the do &#8230; while (0), consult the comp.lang.c FAQ.) [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[25],"class_list":["post-136","post","type-post","status-publish","format-standard","hentry","category-programming","tag-c"],"_links":{"self":[{"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/posts\/136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/comments?post=136"}],"version-history":[{"count":0,"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/posts\/136\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/media?parent=136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/categories?post=136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.slimjimmy.com\/weblog\/wp-json\/wp\/v2\/tags?post=136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}