From: Tommy on
Joy Maitland wrote:
> On Wed, 19 Nov 2008 11:41:22 +0200, "Alex Blekhman"
> <tkfx.REMOVE(a)yahoo.com> wrote:
>
>> "Joy Maitland" wrote:
>>> How can I convert CString to LPCTSTR ?
>> You don't need to. CString already contains `operator LPCTSTR'.
>> Just pass CString object where LPCTSTR is expected.
>>
>
> you mean CString and LPCTSTR are same thing?

no. CString is an object, LPCSTR is a "Long Pointer to Constant
Character String" (TCHAR version). The CString class have operators
(think of them as symbolic functions) which allows you to reference a
CString variable with a const pointer to a character in this string
buffer.

It because says "give me the pointer to the first character in the
buffer you are maintaining. I don't want to change it, I just want to
read it."

> for a function that expect LPCSTR parameter, I can still pass in a
> CString?

Correct. But it has to be compiled for MBCS (not UNICODE)

> somefuncion (LPCTSTR string)
>
> CString cc = "aaa";
> somefunction ( cc );

Right.

LPCSTR is "hungarian-style" notation for

Long Pointer to Const character STRing

which is basically this

const char *

Its a long pointer because it has to do with the fact that in the old
days, memory on Intel boxes was segmented (and still is today), it
wasn't linear like Motorola chips (old MACs) and if the pointer
reference was within the same segment it was considered a short or
near pointer. But if it was outside the segment, it was long or far
pointer.

LPCTSTR is basically the portable TCHAR version:

const TCHAR *

TCHAR is the way you can "single source" character related types for
UNICODE or MBCS compilations. So the practice today is to do

TCHAR *s = "joy";

instead of:

char *s = "joy";

and to further confusion people, the recommendation is to wrap string
with _T, like so:

TCHAR *s = _T("joy");

because the COMPILER needs all the freaking help it can get from you
in the crazy UNICODE world :-)

Anyway, the compiler sees your function, and because the CString class
as an operator for this, it passes a pointer to an ASCIIZ (Null
Terminated) string buffer.

When using LPCTSTR, you can compile for UNICODE or compile for MBCS.

When using LPCSTR, you are only compiling for MBCS. So having

#define UNICODE

#include <afx.h>

somefuncion (LPCSTR string)

CString cc = "aaa";
somefunction ( cc );

will fail to compile because the compiler can't find a LPCSTR for
unicode compiles.

But under non unicode (comment out #define UNICODE), LPCTSTR basically
becomes LPCSTR, thus allowing you to pass a CString object as a const
char *.

You can't mix unless you do conversions.

Go figure, welcome to mass confusion hell. :-)

---
From: David Wilkinson on
Tommy wrote:
>
> CString cc = "aaa";
> somefunction ( cc );
>
> will fail to compile because the compiler can't find a LPCSTR for
> unicode compiles.

Tommy:

Actually, due to regrettable conversion constructors built into CString, the
above will compile in a Unicode build.

It will also run correctly in this case, though not in cases with non-ASCII
characters not using the local code page (for example a UTF-8 string).

--
David Wilkinson
Visual C++ MVP
From: Tommy on
David Wilkinson wrote:
> Tommy wrote:
>>
>> CString cc = "aaa";
>> somefunction ( cc );
>>
>> will fail to compile because the compiler can't find a LPCSTR for
>> unicode compiles.
>
> Tommy:
>
> Actually, due to regrettable conversion constructors built into CString,
> the above will compile in a Unicode build.
>
> It will also run correctly in this case, though not in cases with
> non-ASCII characters not using the local code page (for example a UTF-8
> string).

Thanks, in all honesty, I am still re-catching up to this horror
especially now with greater UTF-XX related needs (i.e. RFC electronic
mail formats). So all insights wrt UNICODE will be greatly
appreciated, :-)

To test my current understanding, I tried this simple test:

// File: G:\wc7beta\testlpctstr.cpp

#define _UNICODE
//#define MBCS

#include <stdio.h>
#include <afx.h>

void funcM(LPCSTR sz) { printf("s M = [%s]\n",sz); }
void funcT(LPCTSTR sz) { printf("s T = [%s]\n",sz); }
void funcC(const TCHAR *sz) { printf("s C = [%s]\n",sz);}

void main(char argc, char *argv[])
{
CString s = "hello";
funcM(s);
funcC(s);
funcT(s);
}

and the compiler issued:

G:\wc7beta\testlpctstr.cpp(16) : error C2664: 'funcM' : cannot
convert parameter 1 from 'CString' to 'LPCSTR' No
user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called

How does this correspond to your note? Did I compile it wrong? Are
you indicating it should of compiled?

I'm using VC8 (cl v14.00.50727.762) and I used no switches.

cl testlpctstr.cpp

I also tried s = _T("hello")

Thanks

--
From: David Wilkinson on
Tommy wrote:
> David Wilkinson wrote:
>> Tommy wrote:
>>>
>>> CString cc = "aaa";
>>> somefunction ( cc );
>>>
>>> will fail to compile because the compiler can't find a LPCSTR for
>>> unicode compiles.
>>
>> Tommy:
>>
>> Actually, due to regrettable conversion constructors built into
>> CString, the above will compile in a Unicode build.
>>
>> It will also run correctly in this case, though not in cases with
>> non-ASCII characters not using the local code page (for example a
>> UTF-8 string).
>
> Thanks, in all honesty, I am still re-catching up to this horror
> especially now with greater UTF-XX related needs (i.e. RFC electronic
> mail formats). So all insights wrt UNICODE will be greatly appreciated, :-)
>
> To test my current understanding, I tried this simple test:
>
> // File: G:\wc7beta\testlpctstr.cpp
>
> #define _UNICODE
> //#define MBCS
>
> #include <stdio.h>
> #include <afx.h>
>
> void funcM(LPCSTR sz) { printf("s M = [%s]\n",sz); }
> void funcT(LPCTSTR sz) { printf("s T = [%s]\n",sz); }
> void funcC(const TCHAR *sz) { printf("s C = [%s]\n",sz);}
>
> void main(char argc, char *argv[])
> {
> CString s = "hello";
> funcM(s);
> funcC(s);
> funcT(s);
> }
>
> and the compiler issued:
>
> G:\wc7beta\testlpctstr.cpp(16) : error C2664: 'funcM' : cannot
> convert parameter 1 from 'CString' to 'LPCSTR' No
> user-defined-conversion operator available that can perform this
> conversion, or the operator cannot be called
>
> How does this correspond to your note? Did I compile it wrong? Are you
> indicating it should of compiled?
>
> I'm using VC8 (cl v14.00.50727.762) and I used no switches.
>
> cl testlpctstr.cpp

Tommy:

I did not say that CString has both LPCSTR and LPCWSTR cast operators, but it
does have constructors and assignment operators that take both LPCSTR and
LPCWSTR as arguments.

These automatic conversion features are very dangerous if you are writing a
mixed UTF-8/UTF-16 application. The Windows code page is (almost) dead, so it is
a great pity that CString has features that are tied to it.

--
David Wilkinson
Visual C++ MVP