Prev: Visual Studio 2008 on Windows 7
Next: std::vector error
From: Igor Tandetnik on 16 Dec 2009 13:13 Leigh Johnston <leigh(a)i42.co.uk> wrote: >> But what about the length/size of the std::string s after you pass >> &s[0] to some API? If s.length() and strlen(s.c_str()) are not the >> same, things could get very confusing. >> > > strlen(s.c_str()) and s.length() will always be the same. string s; s.resize(100); s[0] = 0; // Replace with, say, GetWindowText for added realism assert(strlen(s.c_str()) == s.length()); // oops -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
From: Leigh Johnston on 16 Dec 2009 13:22 You can do a resize() or erase to remove the null terminator after copying to the buffer. You obviously should not use c_str() if it is valid for your std::string string to contain nulls. This is one reason for using std::string over C null terminated strings, the inclusion of length. "Igor Tandetnik" <itandetnik(a)mvps.org> wrote in message news:uA$PstnfKHA.1596(a)TK2MSFTNGP06.phx.gbl... > Leigh Johnston <leigh(a)i42.co.uk> wrote: >>> But what about the length/size of the std::string s after you pass >>> &s[0] to some API? If s.length() and strlen(s.c_str()) are not the >>> same, things could get very confusing. >>> >> >> strlen(s.c_str()) and s.length() will always be the same. > > string s; > s.resize(100); > s[0] = 0; // Replace with, say, GetWindowText for added realism > assert(strlen(s.c_str()) == s.length()); // oops > > -- > With best wishes, > Igor Tandetnik > > With sufficient thrust, pigs fly just fine. However, this is not > necessarily a good idea. It is hard to be sure where they are going to > land, and it could be dangerous sitting under them as they fly > overhead. -- RFC 1925 >
From: Tim Roberts on 20 Dec 2009 18:59 "Leigh Johnston" <leigh(a)i42.co.uk> wrote: > >> 2. Pass a pointer to internal character buffer to Windows API function. > >Trivial to do with std::string.. resize(...) and &s[0] Trivial, and unsafe. &s[0] on a std::string gives you a counted vector, not necessarily a zero-terminated string. The implementation CAN do so, but the standard does not require it. To be safe, you have to use s.c_str(). >> All the above mentioned tasks are quite easy with CString and hard with >> std::string. > >Wrong. No, he's not. "Hard" may be a bit of an exaggeration, but "unnatural" is not. Win32 API code using CString is simply more natural than std::string. -- Tim Roberts, timr(a)probo.com Providenza & Boekelheide, Inc.
From: Tim Roberts on 20 Dec 2009 19:06 "Leigh Johnston" <leigh(a)i42.co.uk> wrote: > >I prefer to have as much of my code to be as portable as possible, hence my >preference for std::string; I can appreciate this goal, but once you start calling SendMessage and GetWindowsDirectory, portability is no longer an issue. That's my basic point. In code that is dealing with the Win32 API, you might as well use CString, since the impedance match is better. In code that CAN be made portable, std::string is a great choice. >I prefer an explicit call to c_str() rather than relying on ugly conversion >operators and it is up to the implementation as to whether c_str() returns a >copy or not, in VC++ it does not return a copy I believe. Quite correct. In fact, in VC++, &s[0] happens to return a zero-terminated buffer, but that's an implementation detail. -- Tim Roberts, timr(a)probo.com Providenza & Boekelheide, Inc.
From: Leigh Johnston on 20 Dec 2009 20:56
> Trivial, and unsafe. &s[0] on a std::string gives you a counted vector, > not necessarily a zero-terminated string. The implementation CAN do so, > but the standard does not require it. To be safe, you have to use > s.c_str(). > You cannot write to the buffer returned by c_str(). You can resize the string to include a possible null terminator, WinAPI write to it via &s[0] (which is contiguous on most sane implementations and guaranteed to be in c++0x), then remove the null terminator with erase. /Leigh |