by Michael S. Kaplan, published on 2008/03/07 08:16 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2008/03/07/8086758.aspx
Please read the disclaimer; content of Michael Kaplan's blog not approved by Microsoft!
So the other day Stephan T. Lavavej (also known by his initials, STL, which also happens to be what he works on!) came by and we chatted for a bit about development stuff.
It was I think a pretty fascinating conversation, you know the kind where two people don't know each other (except crossing paths in emails to distribution lists), where each person knows a bit about something that the other person knows a lot about, but we walk into the conversation knowing that so there is no weirdness or competitive stuff about it....
Anyway, at one point I was talking about that whole issue with lstrcmpi, the one I talked about in How do I feel about lstrcmpi? I think it blows.... and elsewhere.
And I pointed out that people almost universally tend to use the function incorrectly.
"Why?" he asked, genuinely curious.
The question stopped me short.
That kind of consistency is pretty rare, after all.
Why is it so easy to get wrong?
Hmmmm. I hadn't thought about it too much, really.
After he left I thought about it a bit. And then it occurred to me....
If you look at the string functions topic in the Platform SDK, there are six functions that have that naming pattern:
Function | Purpose | kinda like CRT's |
lstrcat | This function appends one null-terminated string to another null-terminated string. | strcat? |
lstrlen | This function returns the length in bytes (ANSI version) or WCHAR values (Unicode version) of the specified null-terminated string (not including the terminating null character). | strlen? |
lstrcpy | This function copies a null-terminated string to a buffer, including the terminating null character. | strcpy? |
lstrcpyn | This function copies a specified number of bytes (ANSI version) or WCHAR values (Unicode version) from a source string null-terminated into a buffer. | strncpy? |
lstrcmp | This function compares two character strings. The comparison is case-sensitive. | strcmp? |
lstrcmpi | This function compares two character strings. The comparison is not case-sensitive. | strcmpi? |
Given that first four functions have such similar behavior to their C runtime counterparts, the similarly named last two can reasonably expected to do the same thing, right?
The fact that they don't is obviously the source of a lot of problems here.
Now if the functions were named lstrcoll and lstrcolli then perhaps the function would not be so commonly misused.
Nobody just ever gave these functions a chance -- it is like giving a child a terrible name that gets them beaten up in school or something!
Nobody I talked to could recall what the lowercase L prefix was intended to mean, either. And now as the CRT deprecates most of these functions in favor of names that fit the ISO standard rather than the POSIX one, the Win32 functions will become even further removed from understanding.
Makes me wonder if Microsoft just ought to deprecate its "L" prefixed family, too!
This blog brought to you by l (U+006c, aka LATIN SMALL LETTER L)
Mike Dimmick on 7 Mar 2008 10:46 AM:
I suspect the l prefix is from 16-bit Windows, where the C runtime might be 'near' and these routines were 'far'. So if you had a 'far' string, pointed to by a 'far' pointer, you needed to use lstrxxx rather than strxxx.
Visual C++ 1.52 documents _fstrcat (etc) in the runtime and that even goes back to C/C++ 6.0, but other compiler vendors may not have supported it.
lstrcmp was added in Windows 3.0 according to the 3.1 SDK help file I have.
The lstrxxx family are also useful for ATL developers who don't want to link to the CRT!
Michael S. Kaplan on 7 Mar 2008 10:53 AM:
But they have to stay away from lstrcmp and lstrcmpi, though. :-)
Plus, no one gets away from the CRT these days....
referenced by