{"id":103290,"date":"2020-01-03T07:00:00","date_gmt":"2020-01-03T15:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103290"},"modified":"2020-01-02T17:51:06","modified_gmt":"2020-01-03T01:51:06","slug":"20200103-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200103-00\/?p=103290","title":{"rendered":"Anybody who writes <CODE>#pragma pack(1)<\/CODE> may as well just wear a sign on their forehead that says &#8220;I hate RISC&#8221;"},"content":{"rendered":"<p>When you use <code>#pragma pack(1)<\/code>, this changes the default structure packing to byte packing, removing all padding bytes normally inserted to preserve alignment.<\/p>\n<p>Consider these two structures:<\/p>\n<pre>\/\/ no #pragma pack in effect.\r\nstruct S\r\n{\r\n    int32_t total;\r\n    int32_t a, b;\r\n};\r\n\r\n#pragma pack(1)\r\n\r\nstruct P\r\n{\r\n    int32_t total;\r\n    int32_t a, b;\r\n};\r\n<\/pre>\n<p>Both structures have identical layouts because the members are already at their natural alignment, Therefore, you would expect these two structures to be equivalent.<\/p>\n<p>But they&#8217;re not.<\/p>\n<p>Changing the default structure packing has another consequence: It changes the alignment of the structure itself. In this case, the <code>#pragma pack(1)<\/code> declares that the structure <code>P<\/code> can itself be placed at any byte boundary, instead of requiring it to be placed on a 4-byte boundary.<\/p>\n<pre>struct ExtraS\r\n{\r\n    char c;\r\n    S s;\r\n    char d;\r\n};\r\n\r\nstruct ExtraP\r\n{\r\n    char c;\r\n    P p;\r\n    char d;\r\n};\r\n<\/pre>\n<p>Even though the structures <code>S<\/code> and <code>P<\/code> have the same layout, the difference in alignment means that the structures <code>ExtraS<\/code> and <code>ExtraP<\/code> end up quite different.<\/p>\n<p>The <code>ExtraS<\/code> structure starts with a <code>char<\/code>, then adds three bytes of padding, followed by the <code>S<\/code> structure, then another <code>char<\/code>, and three more bytes of padding to bring the entire structure back up to 4-byte alignment. This ensures that an array of <code>ExtraS<\/code> structures will properly align all of the embedded <code>S<\/code> objects.<\/p>\n<p>By comparison, the <code>ExtraP<\/code> structure starts out the same way, with a single <code>char<\/code>, but this time, there is no padding before the <code>P<\/code> because the <code>P<\/code> is byte-aligned. Similarly, there is no trail padding at the end of the structure because the <code>P<\/code> is byte-aligned and therefore does not need to be kept at a particular alignment in the case of an array of <code>ExtraP<\/code> objects.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr style=\"border-bottom: solid 2px black;\">\n<td style=\"border-right: solid 2px black;\">\u00a0<\/td>\n<td><tt>00<\/tt><\/td>\n<td><tt>01<\/tt><\/td>\n<td><tt>02<\/tt><\/td>\n<td><tt>03<\/tt><\/td>\n<td><tt>04<\/tt><\/td>\n<td><tt>05<\/tt><\/td>\n<td><tt>06<\/tt><\/td>\n<td><tt>07<\/tt><\/td>\n<td><tt>08<\/tt><\/td>\n<td><tt>09<\/tt><\/td>\n<td><tt>0A<\/tt><\/td>\n<td><tt>0B<\/tt><\/td>\n<td><tt>0C<\/tt><\/td>\n<td><tt>0D<\/tt><\/td>\n<td><tt>0E<\/tt><\/td>\n<td><tt>0F<\/tt><\/td>\n<td><tt>10<\/tt><\/td>\n<td><tt>11<\/tt><\/td>\n<td><tt>12<\/tt><\/td>\n<td><tt>13<\/tt><\/td>\n<\/tr>\n<tr style=\"border-bottom: solid 2px black;\">\n<th style=\"border-right: solid 2px black;\">ExtraS<\/th>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"3\">padding<\/td>\n<td colspan=\"4\"><code>s.total<\/code><\/td>\n<td colspan=\"4\"><code>s.a<\/code><\/td>\n<td colspan=\"4\"><code>s.b<\/code><\/td>\n<td colspan=\"1\"><code>d<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"3\">padding<\/td>\n<\/tr>\n<tr style=\"border-bottom: solid 2px black;\">\n<th style=\"border-right: solid 2px black;\">ExtraP<\/th>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"4\"><code>p.total<\/code><\/td>\n<td colspan=\"4\"><code>p.a<\/code><\/td>\n<td colspan=\"4\"><code>p.b<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"1\"><code>d<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The effect is more noticeable if you have an array of these objects.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr style=\"border-bottom: solid 2px black;\">\n<td style=\"border-right: solid 2px black;\">\u00a0<\/td>\n<td><tt>00<\/tt><\/td>\n<td><tt>01<\/tt><\/td>\n<td><tt>02<\/tt><\/td>\n<td><tt>03<\/tt><\/td>\n<td><tt>04<\/tt><\/td>\n<td><tt>05<\/tt><\/td>\n<td><tt>06<\/tt><\/td>\n<td><tt>07<\/tt><\/td>\n<td><tt>08<\/tt><\/td>\n<td><tt>09<\/tt><\/td>\n<td><tt>0A<\/tt><\/td>\n<td><tt>0B<\/tt><\/td>\n<td><tt>0C<\/tt><\/td>\n<td><tt>0D<\/tt><\/td>\n<td><tt>0E<\/tt><\/td>\n<td><tt>0F<\/tt><\/td>\n<td><tt>10<\/tt><\/td>\n<td><tt>11<\/tt><\/td>\n<td><tt>12<\/tt><\/td>\n<td><tt>13<\/tt><\/td>\n<td><tt>14<\/tt><\/td>\n<td><tt>15<\/tt><\/td>\n<td><tt>16<\/tt><\/td>\n<td><tt>17<\/tt><\/td>\n<td><tt>18<\/tt><\/td>\n<td><tt>19<\/tt><\/td>\n<td><tt>1A<\/tt><\/td>\n<td><tt>1B<\/tt><\/td>\n<td><tt>1C<\/tt><\/td>\n<td><tt>1D<\/tt><\/td>\n<td><tt>1E<\/tt><\/td>\n<td><tt>1F<\/tt><\/td>\n<td><tt>20<\/tt><\/td>\n<td><tt>21<\/tt><\/td>\n<td><tt>22<\/tt><\/td>\n<td><tt>23<\/tt><\/td>\n<td><tt>24<\/tt><\/td>\n<td><tt>25<\/tt><\/td>\n<td><tt>26<\/tt><\/td>\n<td><tt>27<\/tt><\/td>\n<\/tr>\n<tr style=\"border-bottom: solid 2px black;\">\n<th style=\"border-right: solid 2px black;\">ExtraS<\/th>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"3\">padding<\/td>\n<td colspan=\"4\"><code>s.total<\/code><\/td>\n<td colspan=\"4\"><code>s.a<\/code><\/td>\n<td colspan=\"4\"><code>s.b<\/code><\/td>\n<td colspan=\"1\"><code>d<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"3\">padding<\/td>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"3\">padding<\/td>\n<td colspan=\"4\"><code>s.total<\/code><\/td>\n<td colspan=\"4\"><code>s.a<\/code><\/td>\n<td colspan=\"4\"><code>s.b<\/code><\/td>\n<td colspan=\"1\"><code>d<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"3\">padding<\/td>\n<\/tr>\n<tr style=\"border-bottom: solid 2px black;\">\n<th style=\"border-right: solid 2px black;\">ExtraP<\/th>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"4\"><code>p.total<\/code><\/td>\n<td colspan=\"4\"><code>p.a<\/code><\/td>\n<td colspan=\"4\"><code>p.b<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"1\"><code>d<\/code><\/td>\n<td colspan=\"1\"><code>c<\/code><\/td>\n<td colspan=\"4\"><code>p.total<\/code><\/td>\n<td colspan=\"4\"><code>p.a<\/code><\/td>\n<td colspan=\"4\"><code>p.b<\/code><\/td>\n<td style=\"border-right: solid 2px black;\" colspan=\"1\"><code>d<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Observe that in the array of <code>ExtraS<\/code> objects, the <code>s.total<\/code>, <code>s.a<\/code>, and <code>s.b<\/code> are always four-byte aligned. But in the array of <code>ExtraP<\/code> objects, there is no consistent alignment for the members of <code>p<\/code>.<\/p>\n<p>The possibility that any <code>P<\/code> structure could be misaligned has significant consequences for code generation, because all accesses to members must handle the case that the address is not properly aligned.<\/p>\n<pre>void UpdateS(S* s)\r\n{\r\n s-&gt;total = s-&gt;a + s-&gt;b;\r\n}\r\n\r\nvoid UpdateP(P* p)\r\n{\r\n p-&gt;total = p-&gt;a + p-&gt;b;\r\n}\r\n<\/pre>\n<p>Despite the structures <code>S<\/code> and <code>P<\/code> having exactly the same layout, the code generation is different because of the alignment.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>UpdateS<\/th>\n<th>UpdateP<\/th>\n<\/tr>\n<tr>\n<th colspan=\"2\" align=\"center\">Intel Itanium<\/th>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<pre>adds  r31 = r32, 4\r\nadds  r30 = r32  8 ;;\r\nld4   r31 = [r31]\r\nld4   r30 = [r30] ;;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nadd   r31 = r30, r31 ;;\r\nst4   [r32] = r31\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nbr.ret.sptk.many rp\r\n<\/pre>\n<\/td>\n<td valign=\"top\">\n<pre>adds  r31 = r32, 4\r\nadds  r30 = r32  8 ;;\r\nld1   r29 = [r31], 1\r\nld1   r28 = [r30], 1 ;;\r\nld1   r27 = [r31], 1\r\nld1   r26 = [r30], 1 ;;\r\ndep   r29 = r27, r29, 8, 8\r\ndep   r28 = r26, r28, 8, 8\r\nld1   r25 = [r31], 1\r\nld1   r24 = [r30], 1 ;;\r\ndep   r29 = r25, r29, 16, 8\r\ndep   r28 = r24, r28, 16, 8\r\nld1   r27 = [r31]\r\nld1   r26 = [r30] ;;\r\ndep   r29 = r27, r29, 24, 8\r\ndep   r28 = r26, r28, 24, 8 ;;\r\nadd   r31 = r28, r29 ;;\r\nst1   [r32] = r31\r\nadds  r30 = r32, 1\r\nadds  r29 = r32, 2 \r\nextr  r28 = r31, 8, 8\r\nextr  r27 = r31, 16, 8 ;;\r\nst1   [r30] = r28\r\nst1   [r29] = r27, 1\r\nextr  r26 = r31, 24, 8 ;;\r\nst1   [r29] = r26\r\nbr.ret.sptk.many.rp\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<th colspan=\"2\" align=\"center\">Alpha AXP<\/th>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<pre>ldl   t1, 4(a0)\r\n\r\n\r\n\r\n\r\nldl   t2, 8(a0)\r\n\r\n\r\n\r\n\r\naddl  t1, t1, t2\r\nstl   t1, (a0)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nret   zero, (ra), 1\r\n<\/pre>\n<\/td>\n<td valign=\"top\">\n<pre>ldq_u t1, 4(a0)\r\nldq_u t3, 7(a0)\r\nextll t1, a0, t1\r\nextlh t3, a0, t3\r\nbis   t1, t3, t1\r\nldq_u t2, 8(a0)\r\nldq_u t3, 11(a0)\r\nextll t2, a0, t2\r\nextlh t3, a0, t3\r\nbis   t2, t3, t2\r\naddl  t1, t1, t2\r\nldq_u t2, 3(a0)\r\nldq_u t5, (a0)\r\ninslh t1, a0, t4\r\ninsll t1, a0, t3\r\nmsklh t2, a0, t2\r\nmskll t5, a0, t5\r\nbis   t2, t4, t2\r\nbis   t5, t3, t5\r\nstq_u t2, 3(a0)\r\nstq_u t5, (a0)\r\nret   zero, (ra), 1\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<th colspan=\"2\" align=\"center\">MIPS R4000<\/th>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<pre>lw    t0, 4(a0)\r\n\r\nlw    t1, 8(a0)\r\n\r\naddu  t0, t0, t1\r\n\r\njr    ra\r\nsw    t0, (a0)\r\n<\/pre>\n<\/td>\n<td valign=\"top\">\n<pre>lwl   t0, 7(a0)\r\nlwr   t0, 4(a0)\r\nlwl   t1, 11(a0)\r\nlwr   t1, 8(a0)\r\naddu  t0, t0, t1\r\nswl   t0, 3(a0)\r\njr    ra\r\nswr   t0, (a0)\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<th colspan=\"2\" align=\"center\">PowerPC 600<\/th>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<pre>lwz    r4, 4(r3)\r\n\r\n\r\n\r\n\r\n\r\n\r\nlwz    r5, 8(r3)\r\n\r\n\r\n\r\n\r\n\r\n\r\naddu   r4, r4, r5\r\nstw    r4, (r3)\r\n\r\n\r\n\r\n\r\n\r\n\r\nblr\r\n<\/pre>\n<\/td>\n<td valign=\"top\">\n<pre>lbz    r4, 4(r3)\r\nlbz    r9, 5(r3)\r\nrlwimi r4, r9, 8, 16, 23\r\nlbz    r9, 6(r3)\r\nrlwimi r4, r9, 16, 8, 15\r\nlbz    r9, 7(r3)\r\nrlwimi r4, r9, 24, 0, 7\r\nlbz    r5, 8(r3)\r\nlbz    r9, 9(r3)\r\nrlwimi r5, r9, 8, 16, 23\r\nlbz    r9, 10(r3)\r\nrlwimi r5, r9, 16, 8, 15\r\nlbz    r9, 11(r3)\r\nrlwimi r5, r9, 24, 0, 7\r\naddu   r4, r4, r5\r\nstb    r4, (r3)\r\nrlwimi r9, r4, 24, 0, 31\r\nstb    r9, 1(r3)\r\nrlwimi r9, r4, 16, 0, 31\r\nstb    r9, 2(r3)\r\nrlwimi r9, r4, 8, 0, 31\r\nstb    r9, 3(r3)\r\nblr\r\n<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<th colspan=\"2\" align=\"center\">SuperH-3<\/th>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<pre>mov.l @(4, r4), r2\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nmov.l @(8, r4), r3\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nadd   r3, r2\r\n\r\n\r\n\r\n\r\n\r\n\r\nrts\r\nmov.l r2, @r4\r\n<\/pre>\n<\/td>\n<td valign=\"top\">\n<pre>mov.b  @(7, r4), r1\r\nshll8  r1\r\nmov.b  @(6, r4), r2\r\nextu.b r2, r2\r\nor     r2, r1\r\nshll8  r1\r\nmov.b  @(5, r4), r2\r\nextu.b r2, r2\r\nor     r2, r1\r\nshll8  r1\r\nmov.b  @r4, r2\r\nextu.b r2, r2\r\nor     r1, r2\r\nmov.b  @(7, r4), r1\r\nshll8  r1\r\nmov.b  @(6, r4), r3\r\nextu.b r3, r3\r\nor     r3, r1\r\nshll8  r1\r\nmov.b  @(5, r4), r3\r\nextu.b r3, r3\r\nor     r3, r1\r\nshll8  r1\r\nmov.b  @r4, r3\r\nextu.b r3, r3\r\nor     r1, r3\r\nadd    r3, r2\r\nmov.b  r2, @r4\r\nshlr8  r2\r\nmov.b  r2, @(1, r4)\r\nshlr8  r2\r\nmov.b  r2, @(2, r4)\r\nshlr8  r2\r\nrts\r\nmov.b  r2, @(3, r4)\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Observe that for some RISC processors, the code size explosion is quite significant. This may in turn affect inlining decisions.<\/p>\n<p>Moral of the story: Don&#8217;t apply <code>#pragma pack(1)<\/code> to structures unless absolutely necessary. It bloats your code and inhibits optimizations.<\/p>\n<p><b>Bonus chatter<\/b>: Once you make this mistake, you can&#8217;t go back. You allowed the structure to be byte-aligned, and if you remove the spurious <code>#pragma pack(1)<\/code>, you are making the structure more strictly aligned, which will be a breaking change for any clients which used the byte-packed version.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alignment as well as padding.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-103290","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing"],"acf":[],"blog_post_summary":"<p>Alignment as well as padding.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=103290"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103290\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=103290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}