{"id":111185,"date":"2025-05-16T07:00:00","date_gmt":"2025-05-16T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111185"},"modified":"2025-05-21T15:24:12","modified_gmt":"2025-05-21T22:24:12","slug":"20250516-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250516-00\/?p=111185","title":{"rendered":"What&#8217;s with the weird <CODE>wReserved<\/CODE> value at the start of the <CODE>DECIMAL<\/CODE> structure?"},"content":{"rendered":"<p>The <code>DECIMAL<\/code> structure looks like this:<\/p>\n<pre>typedef struct tagDEC {\r\n  USHORT wReserved;\r\n  union {\r\n    struct {\r\n      BYTE scale;\r\n      BYTE sign;\r\n    };\r\n    USHORT signscale;\r\n  };\r\n  ULONG  Hi32;\r\n  union {\r\n    struct {\r\n      ULONG Lo32;\r\n      ULONG Mid32;\r\n    };\r\n    ULONGLONG Lo64;\r\n  };\r\n} DECIMAL;\r\n<\/pre>\n<p>What is the deal with that <code>wReserved<\/code> at the front?<\/p>\n<p>That reserved field comes into play when the <code>DECIMAL<\/code> is placed inside a <code>VARIANT<\/code>.<\/p>\n<p>Let&#8217;s start with this simple version of <code>VARIANT<\/code>:<\/p>\n<pre>typedef struct tagVARIANT {\r\n  uint16_t vt;\r\n  union {\r\n    uint64_t    llVal;\r\n    uint32_t    lVal;\r\n    uint8_t     bVal;\r\n    int16_t     iVal;\r\n    \u27e6 a whole bunch of other things \u27e7\r\n    \u27e6 the largest is 8 bytes        \u27e7\r\n    \u27e6 and requires 8-byte alignment \u27e7\r\n  };\r\n} VARIANT;\r\n<\/pre>\n<p>This simple version is a discriminated union with a large number of possible types. The largest such type is 8 bytes in size and has an alignment of 8 bytes. This means that there are 6 bytes of padding between the discriminant <code>vt<\/code> and the union.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 12em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"6\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Let&#8217;s add the padding explicitly.<\/p>\n<pre>typedef struct tagVARIANT {\r\n  uint16_t vt;\r\n  <span style=\"border: solid 1px currentcolor; border-bottom: none;\">uint16_t pad1;<\/span>\r\n  <span style=\"border: 1px currentcolor; border-style: none solid;\">uint16_t pad2;<\/span>\r\n  <span style=\"border: solid 1px currentcolor; border-top: none;\">uint16_t pad3;<\/span>\r\n  union {\r\n    uint64_t    llVal;\r\n    uint32_t    lVal;\r\n    uint8_t     bVal;\r\n    int16_t     iVal;\r\n    \u27e6 a whole bunch of other things \u27e7\r\n    \u27e6 the largest is 8 bytes        \u27e7\r\n    \u27e6 and requires 8-byte alignment \u27e7\r\n  };\r\n} VARIANT;\r\n<\/pre>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad1<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad3<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Now, the <code>DECIMAL<\/code> type wants to hold a scaled decimal value, so we&#8217;ll need at least a byte for the scale, a bit for the sign, and a lot of bits for the mantissa. If we had to squeeze the <code>DECIMAL<\/code> inside the payload field, there would be only 64 bits available. But wait, there are these extra 48 bits of padding. Maybe we can steal them to hold the scale, sign, and more mantissa bits.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 12em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"6\">(<a href=\"https:\/\/english.stackexchange.com\/questions\/20356\/origin-of-i-can-haz\">I CAN HAZ<\/a> MOAR PAYLOAD?)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Great, we found an additional place to stash 48 bits of information.<\/p>\n<p>Our goal is to have the <code>VARIANT<\/code> laid out like this:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\" rowspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad1<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad3<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<td>for non-<code>DECIMAL<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\"><span style=\"font-size: 80%;\">scale<\/span><\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\">sign<\/td>\n<td style=\"border: solid 1px currentcolor; width: 8em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"4\">mantissa_high<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">mantissa_low<\/td>\n<td>for <code>DECIMAL<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>So let&#8217;s declare our <code>DECIMAL<\/code> structure so that it can nestle right in after the <code>vt<\/code>:<\/p>\n<pre>typedef struct tagDECIMAL\r\n{\r\n  uint8_t scale;\r\n  uint8_t sign;\r\n  uint32_t mantissa_high;\r\n  uint64_t mantissa_low;\r\n} DECIMAL;\r\n\r\ntypedef struct tagVARIANT\r\n{\r\n  uint16_t vt;\r\n  union {\r\n    DECIMAL decVal;\r\n    struct {\r\n      uint16_t pad1;\r\n      uint16_t pad2;\r\n      uint16_t pad3;\r\n      union {\r\n        uint64_t    llVal;\r\n        uint32_t    lVal;\r\n        uint8_t     bVal;\r\n        int16_t     iVal;\r\n        \u27e6 a whole bunch of other things \u27e7\r\n        \u27e6 the largest is 8 bytes        \u27e7\r\n        \u27e6 and requires 8-byte alignment \u27e7\r\n      };\r\n    };\r\n  };\r\n};\r\n<\/pre>\n<p>Oh noes! The result is<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center; font-size: 75%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">10<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">11<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">12<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">13<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">14<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">15<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">16<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">17<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\" rowspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 12em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"6\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad1<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">pad3<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"2\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<td>for non-<code>DECIMAL<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 12em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"6\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"1\"><span style=\"font-size: 80%;\">scale<\/span><\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"1\">sign<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"2\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 8em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"4\">mantissa_high<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">mantissa_low<\/td>\n<td>for <code>DECIMAL<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Our attempt to squeeze out the padding just resulted in even more padding!<\/p>\n<p>The problem is that the <code>DECIMAL<\/code> structure requires padding in order to align the two mantissa fields. There is no way to tell the compiler to <a title=\"How to compress out interior padding in a std::pair and why you don't want to\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240731-00\/?p=110069\"> lay out a structure on the assumption that it always appears as part of a larger structure which misaligns its start address<\/a>. Mind you, even if there were a way to do it, you wouldn&#8217;t want to, because code is allowed to declare a standalone <code>DECIMAL<\/code> structure that is not part of a <code>VARIANT<\/code>, and now your promise is broken.<\/p>\n<p>The unnamed structure we introduced into our <code>VARIANT<\/code> has the same problem as <code>DECIMAL<\/code>, so it too gets alignment padding so that the unnamed structure starts at a multiple of 8.<\/p>\n<p>To get the layout we want, we must move the initial <code>vt<\/code> <i>inside the <code>DECIMAL<\/code><\/i>.<\/p>\n<pre>typedef struct tagDECIMAL\r\n{\r\n  <span style=\"border: solid 1px currentcolor;\">uint16_t reserved;<\/span>\r\n  uint8_t scale;\r\n  uint8_t sign;\r\n  uint32_t mantissa_high;\r\n  uint64_t mantissa_low;\r\n} DECIMAL;\r\n\r\ntypedef struct tagVARIANT\r\n{\r\n  union {\r\n    struct {\r\n      uint16_t vt;\r\n      uint16_t pad1;\r\n      uint16_t pad2;\r\n      uint16_t pad3;\r\n      union {\r\n        uint64_t    llVal;\r\n        uint32_t    lVal;\r\n        uint8_t     bVal;\r\n        int16_t     iVal;\r\n        \u27e6 a whole bunch of other things \u27e7\r\n        \u27e6 the largest is 8 bytes        \u27e7\r\n        \u27e6 and requires 8-byte alignment \u27e7\r\n      };\r\n    };\r\n    DECIMAL decVal;\r\n  };\r\n};\r\n<\/pre>\n<p>The resulting layout is now<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">5<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">7<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">8<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">9<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">A<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">B<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">C<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">D<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">E<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">F<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">vt<\/td>\n<td style=\"border: solid 1px currentcolor; width: 12em; background-color: lch(from currentcolor l c h \/ .25);\" colspan=\"6\">(padding)<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">payload<\/td>\n<td>for non-<code>DECIMAL<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 4em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">reserved<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\"><span style=\"font-size: 80%;\">scale<\/span><\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; background-color: lch(from currentcolor l c h \/ .1);\">sign<\/td>\n<td style=\"border: solid 1px currentcolor; width: 8em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"4\">mantissa_high<\/td>\n<td style=\"border: solid 1px currentcolor; width: 16em; background-color: lch(from currentcolor l c h \/ .1);\" colspan=\"8\">mantissa_low<\/td>\n<td>for <code>DECIMAL<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>When the <code>DECIMAL<\/code> is not part of a <code>VARIANT<\/code> the reserved field is unused. But if it&#8217;s part of a <code>VARIANT<\/code>, it&#8217;s living a double life as a <code>vt<\/code>, and the value will always be <code>VT_DECIMAL<\/code>.<\/p>\n<p>If a <code>VARIANT<\/code> represents a <code>DECIMAL<\/code>, you have the weird case that the <code>vt<\/code> comes from the <code>VARIANT<\/code>, but the other fields come from the <code>DECIMAL<\/code>. Back in the days when the <code>VARIANT<\/code> structure was defined, this sort of data punning was commonplace, and nobody would have batted an eye.<\/p>\n<p>Fortunately, even though compiler-writers might cast side-eye at this sort of thing, the trick is legal in this case because the <code>vt<\/code> and <code>wReserved<\/code> fields are both defined as <code>unsigned short<\/code> and therefore satisfy the &#8220;common initial sequence&#8221; rule. This rule permits accessing the part of a non-active union member that shares a common initial sequence with the active union member. The basic idea is that you look for the longest stretch of initial elements of the two union members that agree in type, and those members can be read from one union member even if the other union member is the active member. (There is of course lots of fine print, but that&#8217;s the basic idea.)<\/p>\n<p><b>Bonus reading<\/b>: <a title=\"Type Punning, Strict Aliasing, and Optimization\" href=\"https:\/\/blog.regehr.org\/archives\/959\"> Type Punning, Strict Aliasing, and Optimization<\/a> by John Regehr.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s where the discriminant goes when the <CODE>DECIMAL<\/CODE> is put &#8220;inside&#8221; a <CODE>VARIANT<\/CODE>.<\/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":[25],"class_list":["post-111185","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s where the discriminant goes when the <CODE>DECIMAL<\/CODE> is put &#8220;inside&#8221; a <CODE>VARIANT<\/CODE>.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111185","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=111185"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111185\/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=111185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}