C++/VB - Pass CString to printf?

Asked By hannes.new
25-Sep-08 03:54 AM
Hi,

Is it safe to pass a CString to printf without explicit (LPCTSTR) cast?

The following MSDN article suggests it is NOT safe:
http://msdn.microsoft.com/en-us/library/awkwbzyc(VS.71).aspx
CString object to a function that takes a variable number of arguments.
...
CString kindOfFruit = "bananas";
int      howmany = 25;
printf( "You have %d %s\n", howmany, (LPCTSTR)kindOfFruit );"


On the other hand, various newsgroup posts claim that CString was designed
specifically in such a way that the (LPCTSTR) cast would not be needed with
printf.

We are a team of 40+ developers who are converting several large projects
from char* to CString, and avoiding (LPCTSTR) would save us a lot of time.

Can someone with insight please clarify what the software developing
community should do in this case?

Thanks,

/ Hannes.
Printf
(1)
LPCTSTR
(1)
MVP
(1)
SoftCircuits
(1)
MSFTNGP
(1)
TK
(1)
KindOfFruit
(1)
HJHA
(1)
  Mikel replied...
27-Sep-08 06:18 PM
Just in case, I would follow MSDN's recommendation. Using the cast
won't do any harm, except for losing some time (is writing code
properly a time loss?), and not using it might do it, so...

com/en-us/library/awkwbzyc(VS.71).aspx
d
th
.
  Giovanni Dicanio replied...
25-Sep-08 08:54 AM
CString is designed in a special way such that this works safely.

Since VC2003 CString is actually a template class, and is derived from
template class CSimpleStringT.
You can read the implementation of CSimpleStringT in <atlsimpstr.h> header.
CSimpleStringT has a private data member:

PXSTR m_pszData;

There is no virtual method, so CSimpleStringT has no v-table pointers
(there's no "lpVtbl").

So, as for memory layout, the "address" of a CSimpleStringT instance could
be safely "reinterpreted" as LPCTSTR (pointing to m_pszData), and this is
why passing CString instances to printf() works without the explicit
static_cast< LPCTSTR >.

Note that Microsoft programmers who wrote CSimpleStringT were very clever,
and put the pointer to CStringData (which is an internal class that stores
information like reference counts to string, etc.) *before* the m_pszData
member of CSimpleStringT.

In fact, you can read that CSimpleStringT::GetData does an "unusual" (but
meaningful) cast like this:

CStringData* GetData() const throw()
{
return( reinterpret_cast< CStringData* >( m_pszData )-1 );
}

This "magic" (actually, clever behaviour) allows safe use of CString
instances (simply derived from CSimpleStringT, with no virtual methods) in
%s slots for printf().

However, in the future this "clever" behaviour and this "magic" may
disappear... so I think that the best investment in future robust code is to
do the explicit static_cast.

Giovanni
  Jonathan Wood replied...
25-Sep-08 02:29 PM
I looked into this at one time. While it works and is safe, I recall that it
is not as efficient. I believe the code generated will create a copy of the
CString object and then pass that. Because of the way the CString class is
designed, it is equal to the address of the string.

By using the cast or calling the GetBuffer() method, you may be producing
much more efficient code.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Tom Serface replied...
25-Sep-08 02:55 PM
That may be significant if you are doing the printf call in a tight loop
like updating status information.

I'd still be more likely to just use CString::Format or
CString::FormatMessage and skip printf altogether.  That is a pretty thin
layer on top of it all.

Tom
  Mark Salsbery [MVP] replied...
25-Sep-08 03:45 PM
Yes, and that's how it should be passed - with NO cast.

Using the cast will hide a bug if you move the code to a Unicode build.


Really, if you're using a generic TCHAR character type string like CString,
then you should be using generic text function mappings.
You should VERY rarely need a string cast if you do..

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Jonathan Wood replied...
25-Sep-08 03:55 PM
Mark,


I must confess that I'm pretty surprised someone would suggest in a thread
like this that the typecast can cause a bug, and yet not even hint at what
that bug might be.

I posted that the typecase can be more efficient, and then explained the
details of why.

Any chance you'll do the same and explain why we should use the less
efficient syntax?

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Jonathan Wood replied...
25-Sep-08 03:59 PM
Tom,


Well, I can tell you that I often use Format and rarely use printf in a
Windows application!

However, that said, Format is not that thin of a wrapper. It actually parses
the format string twice. The first time is to determine the size of the
required buffer. In fact, last time I looked into this, the code to do this
was not in the C run time, it was actually MFC code that parsed through the
format string, looking at each field and determining its length.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  John Sw replied...
25-Sep-08 04:40 PM
I won't speak for anyone else, but the danger here isn't in using the
cast (which as you point out is a good idea). It is in using a dumb
cast. It should really use static_cast<LPCTSTR>(), which will not cause
unexpected conversions and is also Unicode safe. The only reason to use
the C-style casts is to save typing, and we know how much time that
saves in the long run.
  Mark Salsbery [MVP] replied...
25-Sep-08 05:13 PM
On a Unicode build, a const wchar_t * would be passed - that would be a bug.
Of course it shouldn't compile I suppose, so I retract my statements.

The entire subject of using CString with printf() is kind of silly IMO, but
this would be a more proper way to pass a CString:

// This should work on Unicode and non-Unicode builds
CString kindOfFruit = _T("bananas");
int      howmany = 25;
printf("You have %d %s", howmany, CT2A(kindOfFruit) );


Typecasts cause LOTS of bugs.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Tom Walker replied...
25-Sep-08 05:13 PM
it is true that C-style casts should be avoided, but a C++ static_cast is
safe:
static_cast<LPCTSTR>(myStr);

However, the CString::GetString method is cleaner:
myStr.GetString();
  Mark Salsbery [MVP] replied...
25-Sep-08 05:15 PM
I was wrong again - the code I described as a bug (using that cast in a
Unicode build) WOULD compile with no warning/error.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Mark Salsbery [MVP] replied...
25-Sep-08 05:17 PM
My point was Unicode build in this specific instance.  Try the OP's code on
a Unicode build - you'll see what I mean.
A static cast won't fix that - the string needs to be converted to ANSI.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Mark Salsbery [MVP] replied...
25-Sep-08 05:34 PM
Safe?  Maybe, but it does not work, unless the 'b' in the string "bananas" is
all you wanted.  Try it.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Jonathan Wood replied...
25-Sep-08 05:46 PM
Mark,


Ah... got ya. Personally, I don't consider that a bug in the typecast. But
if you are calling printf in a Unicode app, then you definitely need to know
what you are doing.


Sure, but this code would probably be better written to call _tprintf
instead of printf.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Jonathan Wood replied...
25-Sep-08 05:49 PM
I must be getting old. I still use the only type of cast available back when
I learned C.

Can anyone tell me the difference, specifically, in the code generated by
the compiler for these two statements?

1. p = static_cast<LPCTSTR>(myStr);
2. p = (LPCTSTR)myStr;

Thanks.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Jonathan Wood replied...
25-Sep-08 05:51 PM
A cast to LPCTSTR in an argument to printf() in a Unicode build, should
cause a warning/error. In a Unicode build, LPCTSTR is LPCWSTR and printf()
expects LPCSTR.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  David Wilkinson replied...
25-Sep-08 06:03 PM
Mark:

I'm not quite sure what your point is here. If it is that you should always use
_tprintf() or CString::Format() rather than printf(), then I would agree with
you. But surely then it does not matter whether you use the LPCTSTR cast or not.

But suppose you do use printf(). In a Unicode build I can see that you will not
get the answer you expect, but what is the difference between using the LPCTSTR
cast or not?

--
David Wilkinson
Visual C++ MVP
  Mark Salsbery [MVP] replied...
25-Sep-08 06:11 PM
Whatever :)  The entire statement would cause bug-like behavior at runtime.




Agreed - I'd go further and state one should know what they're doing when
using CString.

My original main point was really mixing fixed string types with generic
string types is, umm, counterproductive?  It renders the whole usefulness of
generic string types useless.




I totally agree - that's why I mentioned the generic text mappings in my OP

Cheers,
Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Mark Salsbery [MVP] replied...
25-Sep-08 06:17 PM
That's what I originally thought, but with var args the compiler doesn't
give a warning even at level 4.

Here's my test code for this thread:

//
// Tested on Visual Studio 2008 SP1
//
CString kindOfFruit = _T("bananas");
int      howmany = 25;
char buff[80];
sprintf(buff, "You have %d %s", howmany, CT2A(kindOfFruit) );
sprintf(buff, "You have %d %s", howmany, (LPCTSTR)kindOfFruit );
sprintf(buff, "You have %d %s", howmany, static_cast<LPCTSTR>(kindOfFruit));


No warnings (except the deprecated functions).

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Alexander Grigoriev replied...
25-Sep-08 06:41 PM
Because CString is not a simple type, like an integer or pointer, (LPCTSTR)
cast is only interpreted as static_cast.
  Alexander Grigoriev replied...
25-Sep-08 06:42 PM
LPCTSTR cast of CString is always safe. There is NO cast to the "other"
string pointer (LPCXSTR) provided by CString; such a cast won't compile.

For CString, C-style LPCTSTR cast (or LPCTSTR(s)) can only be interpreted
one way: by invoking LPCTSTR operator. There is no reinterpret_cast
interpretation for that, because the source is not a builtin type.
  Alexander Grigoriev replied...
25-Sep-08 06:42 PM
Why? This is a variadic function, with arguments of any POD type.
  Mark Salsbery [MVP] replied...
25-Sep-08 06:44 PM
That was my point yes.  The mixing of generic and non generic strings is a
peeve of mine.  It's the number one source of string-related bugs IME
looking at people's posted code.

I suppose I should have said nothing.




I didn't say there was a difference (I don't think).

Jonathan Wood stated using the cast is more efficient, but I just looked at
the disassembly of my test code (below) and it seems NOT using the cast is
the most efficient.  I could be wrong :)

//
// Test platform:  VS 2008 SP1 on Vista Ultimate
//
//   Unicode build!
//
CString kindOfFruit = _T("bananas");
int      howmany = 25;
char bufff[250];
sprintf(bufff, "You have %d %s", howmany, kindOfFruit);
sprintf(bufff, "You have %d %s", howmany, (LPCTSTR)kindOfFruit );
sprintf(bufff, "You have %d %s", howmany,
static_cast<LPCTSTR>(kindOfFruit));
sprintf(bufff, "You have %d %s", howmany, CT2A(kindOfFruit) );



Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Giovanni Dicanio replied...
25-Sep-08 06:43 PM
I think that, if the class has a operator LPCTSTR() for conversion, like
CString has, these are equivalent.

However, the point is doing:

CString myStr;

_tprintf( TEXT("My string: %s"), myStr ); // #1

vs.

_tprintf( TEXT("My string: %s"), (LPCTSTR)myStr ); // #2

I believe #2 is equivalent to:

_tprintf( TEXT("My string: %s"), static_cast< LPCTSTR >(myStr) );

Instead, #1 is possible thanks to CStringT/CSimpleStringT memory layout,
that I tryed to explain in my first post, and is confirmed also by this
working code:

CString str = TEXT("ciao");
const TCHAR * psz = *reinterpret_cast< const TCHAR ** >(&str);

the debugger shows "ciao" for 'psz'.

Giovanni
  Mark Salsbery [MVP] replied...
25-Sep-08 06:52 PM
Ok.  I'm not sure how any of that applies to and/or contradicts any
statements I made  :)

The cast is is not only perfectly fine in the OP's case, but it isn't even
necessary.


My point was that it would not give the desired results on a Unicode build.

IMO either use generic types (e.g. TCHAR, CString, generic-text mapped
functions) everywhere or use specific types (e.g. CStringA, CStringT, char,
printf()).

Mixing them makes non-portable code and introduces undesired behavior, as
demonstrated by the OP's code built with UNICODE/_UNICODE defined.


Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Jonathan Wood replied...
25-Sep-08 08:15 PM
Doh! You're right. The format string must be the right type, but any
additional arguments are untyped.

'scuse me.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Jonathan Wood replied...
25-Sep-08 08:16 PM
Yes, I've already been corrected on this. The format string must be of the
correct type, but all arguments after that are untyped.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Jonathan Wood replied...
25-Sep-08 08:16 PM
So, if I follow, it does not matter in this case. Which is what I was
thinking.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Alexander Grigoriev replied...
25-Sep-08 08:23 PM
Passing non-POD to a variadic function is not valid C++. Microsoft CSTring
documentation EXPLICITLY says that you need LPCTSTR cast.


Both cast and non-cast won't magically make the argument with the necessary
type. Such is danger of printf and alike functions.
  Jonathan Wood replied...
25-Sep-08 08:23 PM
Mark,


Some time ago, I looked into this. At that time, passing a CString object
untyped to _tprintf() caused a copy of the CString to be created and then
passed to _tprintf(). It still works because of the memory layout. On the
other hand, passing the address of the string withing the CString object
requires no memory to be copied.

I suppose it's possible this has changed but I strongly suspect it has not.
If you have something that shows the typecast is not more efficent, please
share.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  David Wilkinson replied...
25-Sep-08 09:11 PM
Mark:

Maybe the assembly is not exactly the same, but don't the first three all give
the same "wrong" result, but without doing any actual conversion or memory
allocation?

While the last gives the "right" result, at the cost of a conversion (and a
memory allocation if the string is big enough).

--
David Wilkinson
Visual C++ MVP
  Mark Salsbery [MVP] replied...
25-Sep-08 09:16 PM
I posted the code along with my test platform info in the post you responded
to here.

I'm not agreeing or disagreeing with your comments.
I just looked at the disassembly of a non-optimized build of the code I
posted and it looked like not using the cast was the most efficient.
I also said I may be wrong.  I'll leave it for someone else to
prove/disprove.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Mark Salsbery [MVP] replied...
25-Sep-08 09:26 PM
Here's what I see - VC 9 compiler, debug build, no optimizations.
Without cast and with...

sprintf(bufff, "You have %d %s", howmany, kindOfFruit);
00420E5A  mov         esi,esp
00420E5C  mov         eax,dword ptr [ebp-24h]
00420E5F  push        eax
00420E60  mov         ecx,dword ptr [ebp-30h]
00420E63  push        ecx
00420E64  push        offset string "You have %d %s" (446B88h)
00420E69  lea         edx,[ebp-134h]
00420E6F  push        edx
00420E70  call        dword ptr [__imp__sprintf (0A1E650h)]
00420E76  add         esp,10h
00420E79  cmp         esi,esp
00420E7B  call        @ILT+5270(__RTC_CheckEsp) (41649Bh)


sprintf(bufff, "You have %d %s", howmany, (LPCTSTR)kindOfFruit );
00420E80  mov         esi,esp
00420E82  lea         ecx,[ebp-24h]
00420E85  call        dword ptr
[__imp_ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const * (0A1EB98h)]
00420E8B  cmp         esi,esp
00420E8D  call        @ILT+5270(__RTC_CheckEsp) (41649Bh)
00420E92  mov         esi,esp
00420E94  push        eax
00420E95  mov         eax,dword ptr [ebp-30h]
00420E98  push        eax
00420E99  push        offset string "You have %d %s" (446B88h)
00420E9E  lea         ecx,[ebp-134h]
00420EA4  push        ecx
00420EA5  call        dword ptr [__imp__sprintf (0A1E650h)]
00420EAB  add         esp,10h
00420EAE  cmp         esi,esp
00420EB0  call        @ILT+5270(__RTC_CheckEsp) (41649Bh)


I'm open to any interpretation of which is more efficient :)

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Mark Salsbery [MVP] replied...
25-Sep-08 09:46 PM
Sure.

I just threw the code out there (based on the OP's code) for anyone In this
discussion to test with.

I did all four to test the validity of the efficiency comments.
The static_cast version assembly is identical to the C-style cast.
And yes, the one that does the conversion takes the most instructions but
yields the correct result on a Unicode build.

I'm really not sure what's being discussed at this point - I only originally
meant to respond to the OP.

Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Jonathan Wood replied...
25-Sep-08 09:48 PM
Yep. In your example, the typecast version calls the LPCTSTR operation
method, which is less efficient.

Note that this will not happen in a release build. However, I did a test of
my own and looked at the release code. It looks like the CString object is
not copied as I had earlier observed.

Therefore, in this partiuclar example (my test used _tprintf()), there
doesn't appear to be any difference between passing the CString object with
and without a typecast as an untyped argument.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
  Mark Salsbery [MVP] replied...
25-Sep-08 10:22 PM
Confirmed.

sprintf(bufff, "You have %d %s", howmany, kindOfFruit);
00405596  mov         eax,dword ptr [ebp-1B8h]
0040559C  push        eax
0040559D  mov         ecx,dword ptr [ebp-308h]
004055A3  push        ecx
004055A4  push        413590h
004055A9  lea         edx,[ebp-814h]
004055AF  push        edx
004055B0  call        dword ptr [__imp__sprintf (4111E4h)]
004055B6  add         esp,10h

sprintf(bufff, "You have %d %s", howmany, (LPCTSTR)kindOfFruit );
004055B9  lea         ecx,[ebp-1B8h]
004055BF  call        dword ptr
[__imp_ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const * (411838h)]
004055C5  push        eax
004055C6  mov         eax,dword ptr [ebp-308h]
004055CC  push        eax
004055CD  push        4135A0h
004055D2  lea         ecx,[ebp-814h]
004055D8  push        ecx
004055D9  call        dword ptr [__imp__sprintf (4111E4h)]
004055DF  add         esp,10h


Good to know.  I appreciate the discussion, thanks!!

Cheers,
Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  David Wilkinson replied...
26-Sep-08 06:53 AM
Mark:

I am not quite sure either...

I certainly agree with you that mixed char/TCHAR code is a major source of
confusion and error.

--
David Wilkinson
Visual C++ MVP
  John Sw replied...
26-Sep-08 12:09 PM
You're right and I wasn't thinking. The cast is Unicode safe, but it
isn't correct when you are calling a non-Unicode function. I'll still
stand by the fact that you should use C++ casts, not C casts and you
should cast varargs arguments if you want to be sure you get what you
want. If the type is known, unnecessary casts of any type are a bad idea.
  John Sw replied...
26-Sep-08 12:16 PM
In this case, there should be no difference. The problem is that the
(LPCTSTR) cast might be doing any of three different types of casts
(changing type, safe conversions, const casting) all at the same time
and they might not all be what you want. In some cases using this type
of cast instead of a dynamic_cast can result in you getting the wrong
pointer to an object (e.g., with multiple inheritance).

I'm definitely getting old, but one thing I've learned in the last
twenty plus years is that code generation is only a small part of what
we need to be concerned about.
  Joseph M. Newcomer replied...
26-Sep-08 12:55 PM
The bug is not related to the cast at all.  Whether the cast is present or not, passing a
pointer to a Unicode string to a printf (which uses 8-bit characters) is going to produce
incorrect output if compiled for Unicode.
joe


Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
  Joseph M. Newcomer replied...
26-Sep-08 01:03 PM
BUt what if the programmer used %S as a formatting string?  Passing an LPCWSTR is
perfectly valid and will work.  There is NO type-checking of the arguments in the ...
part.

%hs always means "8-bit string formatting"; %ls always means "wide-character string
formatting", %S means "the other kind of formatting", that is, it means %hs for a
w-formatting operation and %ls for an a-formatting operation.

So it is always legitimate to write
CStringW s;
s = ...;
printf("%ls", s);
or
printf("%ls", (LPCWSTR)s);

so type-checking makes no sense, since you can't, without parsing the formatting string
(which might not be a compile-time constant) tell what types are required.  So the
compiler simply trusts that you know what you are doing.
joe


Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
  Mark Salsbery [MVP] replied...
26-Sep-08 01:34 PM
Agreed!

Cheers,
Mark

--
Mark Salsbery
Microsoft MVP - Visual C++
  Leo Violette replied...
09-Oct-08 04:43 PM
Not true.  There are cases where it is perfectly valid to pass a UNICODE
character pointer to a printf style function.

Unless you expect the compiler to parse the format string (the %s's and %d's
and whatnot) to determine what arguments would be
valid and then give a warning if one of those arguments don't match.  I
certainly don't expect that of the compiler.  They would have to update
the compiler everytime some coder decides to enhance the printf style
functions.

printf allows a %S (note capital S).  If it encounters one, then it's
expecting a wchar_t*.
Likewise, if wprintf encounters a %S, it wll expect a char*.
Leo V.
Create New Account
help
implementing printf() in mfc C++ / VB Hi all, I have listbox in my dialog based mfc application. Now MFC doesnt have a direct printf like in C. So i want to provide that functionality to the user. So whenever where the api is implemented. How do i go about it ??? kunal VC MFC Discussions MVP (1) LPCTSTR (1) CMyListBox (1) AfxMessageBox (1) FormatV (1) CMyGuiWriter (1) SendMessage (1) GetSafeHwnd (1) You could or if you must use the Win32 API call: ::SendMessage(cListBox.GetSafeHwnd(), LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)sUserString); http: / / www.codeproject.com / combobox / listbox_tut.asp http: / / msdn2.microsoft.com / en-us / library things and then print it on the list box. Instead if i use old style printf, it will done in one line kunal I know how to add data to listbox you didnt get my question. I want to provide the user additional functionality of using printf statement to print in listbox. CString method Format is the not best option. Consider the them before printing. This is too much of hassle but i have simple C style printf, i can do it in one line. So i want to how do C implement
converting char to LPCTSTR? C++ / VB I am using some winsock code in a GUI app written in Win32 the function I'm using from the Win32 API: BOOL SetDlgItemText( HWND hDlg, int nIDDlgItem, LPCTSTR lpString ); Notice the 4th parameter is the actual string, but its data type is LPCTSTR, which is a long pointer to a unicode string. Does anyone know how to convert a standard char type into a LPCTSTR type? There has to be a way to do it. This seems like it would a console app since there is no use of unicode. If I were to use printf() or cout, its fine.) VC Language Discussions WinCE (1) Outlook (1) Vista (1) MultiByteToWideChar (1 convenient ways of doing this (using CString or A2W for example). - - David Wilkinson Visual C++ MVP USES_CONVERSION; LPCTSTR n; n = A2CT ("Example string"); Brian SetDlgItemText() works with plain ol' ASCII, just add â ”. What's this world coming to? Jeff came the closest to a good answer. LPCTSTR does not mean a unicode string, that would be LPCWSTR or LPWSTR or BSTR or
VB Where I work, I'm finding more code like the following: assume: void foo2(LPCTSTR pszVal, int iVal); void foo() { CString str(_T("Some Text")); DWORD dwVal = 40; foo2(LPCTSTR(str), int(dwVal)); / / I prefer the cast syntax: foo2((LPCTSTR)str, (int)dwVal); } I don't like the way they are casting to LPCTSTR and int. Although, it does appear to work. But the syntax is implying that you are constructing a temporary instance of an object. Since LPCTSTR and int are not classes, I think that coding style is misleading. In my opinion casts (i.e. static_cast and friends) when casting is actually appropriate? - - Doug Harrison Visual C++ MVP Just because they aren't classes doesn't mean you can create a temporary instance And those two casts are doing VERY different things. In the case of CString to LPCTSTR, that's actually executing a class method (CString::operator LPCTSTR), so it's doing a lot more than just a cast. What makes you so
CString to LPCTSTR C++ / VB How can I convert CString to LPCTSTR ? VC Language Discussions MACs (1) GmbH (1) Geschäftsführer (1) Amtsgericht (1) Thorsten (1) Windows (1) Hamburg (1) FuncC (1) You do not need to. CString already contains `operator LPCTSTR'. Just pass CString object where LPCTSTR is expected. HTH Alex you mean CString and LPCTSTR are same thing? for a function that expect LPCSTR parameter, I can still pass in a CString? somefuncion (LPCTSTR string) CString cc = "aaa"; somefunction ( cc ); No, class CString has a user-defined conversion operator to LPCTSTR. Yes, that works, exactly because of the above mentioned conversion. Uli - - C++ FAQ: http: / / parashift B62 932 No, they are different types. But CString knows how to convert itself to LPCTSTR if required. You mean LPCTSTR, not LPCSTR, yes? Yes, this will work. Also, you should