{"id":11193,"date":"2011-03-17T07:00:00","date_gmt":"2011-03-17T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/03\/17\/what-does-the-l-in-lstrcmp-stand-for\/"},"modified":"2011-03-17T07:00:00","modified_gmt":"2011-03-17T07:00:00","slug":"what-does-the-l-in-lstrcmp-stand-for","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110317-00\/?p=11193","title":{"rendered":"What does the &#034;l&#034; in lstrcmp stand for?"},"content":{"rendered":"<p>If you ask <a href=\"http:\/\/blogs.msdn.com\/michkap\/\"> Michael Kaplan<\/a>, he&#8217;d probably say that <a href=\"http:\/\/blogs.msdn.com\/michkap\/archive\/2008\/03\/07\/8086758.aspx\"> it stands for <i>lame<\/i><\/a>.\n In his article, Michael presents a nice chart of the various L-functions and their sort-of counterparts. There are other L-functions not on his list, not because he missed them, but because they don&#8217;t have anything to do with characters or encodings. On the other hand, those other functions help shed light on the history of the L-functions. Those other functions are <i>lopen<\/i>, <i>lcreat<\/i>, <i>lread<\/i>, <i>lwrite<\/i>, <i>lclose<\/i>, and <i>llseek<\/i>. There are all L-version sort-of counterparts to <i>open<\/i>, <i>creat<\/i>, and <i>read<\/i>, <i>write<\/i>, <i>close<\/i>, and <i>lseek<\/i>. Note that we&#8217;ve already uncovered the answer to the unasked question &#8220;Why does llseek have two L&#8217;s?&#8221; The first L is a prefix (whose meaning we will soon discover) and the second L comes from the function it&#8217;s sort-of acting as the counterpart to.\n But what does the L stand for? Once you find those other L-functions, you&#8217;ll see next door the H-functions <i>hread<\/i> and <i>hwrite<\/i>. As we learned a while back, <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/12\/12\/9199378.aspx\"> being lucky is simply observing things you weren&#8217;t planning to observe<\/a>. We weren&#8217;t expecting to find the H-functions, but there they were, and they blow the lid off the story.\n The H prefix in <i>hread<\/i> and <i>hwrite<\/i> stands for <i>huge<\/i>. Those two functions operated on so-called <i>huge pointers<\/i>, which is 16-bit jargon for pointers to memory blocks larger than 64KB. To increment your average 16:16 pointer by one byte, you increment the bottom 16 bits. But when the bottom 16 bits contain the value 0xFFFF, the increment rolls over, and where do you put the carry? If the pointer is a huge pointer, the convention is that the byte that comes after <code>S:0xFFFF<\/code> is <code>(S+__AHINCR):0x0000<\/code>, where <code>__AHINCR<\/code> is a special value exported by the Windows kernel. If you allocate memory larger than 64KB, the <code>GlobalAlloc<\/code> function breaks your allocation into 64KB chunks and arranges them so that incrementing the selector by <code>__AHINCR<\/code> takes you from one chunk to the next.\n Working backwards, then, the L prefix therefore stands for <i>long<\/i>. These functions explicitly accept far pointers, which makes them useful for 16-bit Windows programs since they are independent of the program&#8217;s memory model. Unlike the L-functions, the standard library functions like <code>strcpy<\/code> and <code>read<\/code> operate on pointers whose size match the data model. If you write your program in the so-called <i>medium memory model<\/i>, then all data pointers default to <i>near<\/i> (i.e., they are 16-bit offsets into the default data segment), and all the C runtime functions operate on near pointers. This is a problem if you need to, say, read some data off the disk into a block of memory you allocated with <code>GlobalAlloc<\/code>: That memory is expressible only as a far pointer, but the <i>read<\/i> function accepts a near pointer.\n To the rescue comes the <code>lread<\/code> function, which you can use to read from the disk into your far pointer.\n How did Windows decide which C&nbsp;runtime functions should have corresponding L-functions? <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/07\/10\/3799014.aspx\"> They were the functions that Windows itself used internally<\/a>, and which were exported as a courtesy.\n Okay, now let&#8217;s go back to the Lame part. Michael Kaplan notes that the <code>lstrcmp<\/code> and <code>lstrcmpi<\/code> functions actually are sort-of counterparts to <code>strcoll<\/code> and <code>strcolli<\/code>. So why weren&#8217;t these functions called <code>lstrcoll<\/code> and <code>lstrcolli<\/code> instead?<\/p>\n<p> Because back when <code>lstrcmp<\/code> and <code>lstrcmpi<\/code> were being named, the <code>strcoll<\/code> and <code>strcolli<\/code> functions hadn&#8217;t been invented yet! It&#8217;s like asking, &#8220;Why did the parents of General Sir Michael Jackson give him the same name as the pop singer?&#8221; or &#8220;<a href=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/01\/19\/10117410.aspx\">Why didn&#8217;t they use the Space Shuttle to rescue the Apollo 13 astronauts<\/a>?&#8221; <\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you ask Michael Kaplan, he&#8217;d probably say that it stands for lame. In his article, Michael presents a nice chart of the various L-functions and their sort-of counterparts. There are other L-functions not on his list, not because he missed them, but because they don&#8217;t have anything to do with characters or encodings. On [&hellip;]<\/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":[2],"class_list":["post-11193","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>If you ask Michael Kaplan, he&#8217;d probably say that it stands for lame. In his article, Michael presents a nice chart of the various L-functions and their sort-of counterparts. There are other L-functions not on his list, not because he missed them, but because they don&#8217;t have anything to do with characters or encodings. On [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11193","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=11193"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11193\/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=11193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}