{"id":106836,"date":"2022-07-06T07:00:00","date_gmt":"2022-07-06T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106836"},"modified":"2022-07-06T07:02:08","modified_gmt":"2022-07-06T14:02:08","slug":"20220706-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220706-00\/?p=106836","title":{"rendered":"The empty Windows Runtime string is not just a pretty face"},"content":{"rendered":"<p>As I noted <a title=\"Raymonds complete guide to HSTRING semantics\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160615-00\/?p=93675\"> some time ago<\/a>, the empty Windows Runtime string is represented by a null pointer. This has natural but perhaps surprising consequences: Even though it is a null pointer, the empty Windows Runtime string is a real string, with hopes and dreams. Or at least a length and data.<\/p>\n<p>At the ABI level, <code>Windows\u00adGet\u00adString\u00adLen<\/code> reports that a null pointer string has a length of zero, and <code>Windows\u00adGet\u00adString\u00adRaw\u00adBuffer<\/code> gives you a buffer that consists of a single null terminator.<\/p>\n<p>Since an empty string and a null pointer are indistinguishable at the ABI layer, if you operate at the ABI layer (using raw <code>HSTRING<\/code>s) or at a thin projection layer (such as C++\/CX and C++\/WinRT), you can take advantage of this equivalence.<\/p>\n<p>For starters, you don&#8217;t need to check for a null pointer before trying to use the string, because a null pointer is a perfectly valid <code>HSTRING<\/code>.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; font-size: 80%;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>ABI<\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != nullptr &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0WindowsGetStringLen(s) == 1)<\/code><\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != nullptr &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0s == HStringReference(L\"hi\").Get())<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/CX<\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != nullptr &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0s-&gt;Length() == 1)<\/code><\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != nullptr &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0s == L\"hi\")<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/WinRT<\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != hstring{} &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0s.size() == 1)<\/code><\/td>\n<td><code>if (<span style=\"text-decoration: line-through;\">s != hstring{} &amp;&amp;<\/span><br \/>\n\u00a0\u00a0\u00a0\u00a0s == L\"hi\"sv)<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If you are checking for a nonempty string, you can just check for null. C++\/WinRT and C++\/CX even have special methods that tell you directly.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<th>Slower way<\/th>\n<th>Quicker way<\/th>\n<\/tr>\n<tr>\n<td>ABI<\/td>\n<td><code>if (WindowsGetStringLen(s) != 0)<\/code><\/td>\n<td><code>if (s != nullptr)<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/CX<\/td>\n<td><code>if (s-&gt;Length() != 0)<\/code><\/td>\n<td><code>if (!s-&gt;IsEmpty())<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/WinRT<\/td>\n<td><code>if (s.size() != 0)<\/code><\/td>\n<td><code>if (!s.empty())<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Related<\/b>: <a title=\"The C++\/CX String^ is not an object, even though it wears a hat\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211230-00\/?p=106063\"> The C++\/CX <code>String^<\/code> is not an object, even though it wears a hat<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It really is an empty string.<\/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-106836","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It really is an empty string.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106836","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=106836"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106836\/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=106836"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106836"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106836"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}