LPCTSTR

Started by
9 comments, last by maya18222 15 years, 10 months ago
Hi all, I am working with DirectX in Cplusplus. Alot of DirectX fuctions require a LPCTSTR parameter. I have been using LPCTSTR's for a while now, but I don't really understand how they work. I believe LPCTSTR = Long Pointer Const T STRing. What is the difference between a string and a const string? If 'const' means it cannot be changed, then what use would it ever be? I need some basic understanding here please. Also, what if I did this:

LPCTSTR stringy;
stringy = "cheese";
Logic tells me that should not work because: 'stringy' is a pointer, meaning it holds a memory adress, not a string. Yet miraculously, it DOES work :S WHY? I assume the reason DirectX works with pointers to strings, is because it is more efficient to pass around memory adresses, then to move the actual strings around. Is this a correct assumption? The reason I ask all this now is I can't get this to work:

std::ifstream mapData;
    
mapData.open("normalMaps.txt");

std::string currentLine;
std::getline(mapData, currentLine);
pGameObj->statusStr = currentLine.c_str();

mapData.close();

pGameObj->statusStr is a LPCTSTR which I display on the screen, as a debugger. error C2440: '=' : cannot convert from 'const char *' to 'LPCTSTR' Basically I want to stop messing around and actually know what I am doing.
Advertisement
Required reading

As for const strings; if a string is const then you can't change the contents of the string. Which is frequently A Good Thing. For example:
char* GetAppName(){   return "My Awesome Application";}char* szName = GetAppName();strcat(szName, " or something");

That will happily crash your application, because the memory contained by "My Awesome Application" is read only. If GetAppName() returned a const char*, then you'd get a compile error which is infinitely better than a runtime error.
Quote:Original post by Viperrr
Hi all,

I am working with DirectX in Cplusplus. Alot of DirectX fuctions require a LPCTSTR parameter. I have been using LPCTSTR's for a while now, but I don't really understand how they work.

I believe LPCTSTR = Long Pointer Const T STRing.

What is the difference between a string and a const string?
If 'const' means it cannot be changed, then what use would it ever be? I need some basic understanding here please.

Also, what if I did this:
*** Source Snippet Removed ***
Logic tells me that should not work because:
'stringy' is a pointer, meaning it holds a memory adress, not a string.
Yet miraculously, it DOES work :S WHY?


I assume the reason DirectX works with pointers to strings, is because it is more efficient to pass around memory adresses, then to move the actual strings around. Is this a correct assumption?


The reason I ask all this now is I can't get this to work:
*** Source Snippet Removed ***
pGameObj->statusStr is a LPCTSTR which I display on the screen, as a debugger.
error C2440: '=' : cannot convert from 'const char *' to 'LPCTSTR'



Basically I want to stop messing around and actually know what I am doing.


I assume the reason DirectX works with pointers to strings, is because it is more efficient to pass around memory adresses, then to move the actual strings around. Is this a correct assumption?

Yep. Same with references.
If you write it in this order it's easier to understand

char const * const

which means a pointer which is constant pointing to characters which are constant.

char const *

mean a variable pointer which points to characters which are constant. So the first const is a modifier on what the pointer points to not of the pointer itself.

Dave,
I think the LPCTSTR and so on is because it's COM and requires strings to be according to spec. C++ strings are very hard to use cross language boundaries and even cross compilers and cross different STL versions from the same vendor.
Hi there,

Quote:
I believe LPCTSTR = Long Pointer Const T STRing.

What is the difference between a string and a const string?
If 'const' means it cannot be changed, then what use would it ever be? I need some basic understanding here please.

Also, what if I did this:

LPCTSTR stringy;
stringy = "cheese";

Logic tells me that should not work because:
'stringy' is a pointer, meaning it holds a memory adress, not a string.
Yet miraculously, it DOES work :S WHY?


You are correct that LPCTSTR is pointer to a const string. But if you assign a hard coded string like "cheese" in c++, the string is placed in a string table in your program, and the memory address of this string is used instead. So, when you assign "cheese" to stringy, you actually assign the memory address of "cheese" to stringy, no string is copied or duplicated or anything. (remember though, because "cheese" is in the programs string table, you should not delete or free it).

About your second fragment, I do not understand why you get the error, I tried the following myself:

#include <windows.h>int main(){	LPCTSTR str;	const char *c = "cheese";	str = c;	return 0;}


and it did not even give a warning. I can only think of one thing, LPCTSTR can also point to a widestring, depending on if you compiled with UNICODE characters instead of ANSI. If so, LPCTSTR is a pointer to 16-bit wide-charachter string instead of 8-bit ANSI-characters string. I tried it, and on my compiler it gave the error:

error C2440: '=' : cannot convert from 'const char *' to 'const unsigned short *'

But thats the only thing I can think of.
He probably gets a warning because it should be

LPCTSTR mystr = _T("cheese")

since it's a LPCTSTR. char * and TCHAR strings aren't interchangeable. You should stick to either string format and not mix and match or you won't be able to compile both multi byte and utf16 versions of your software.
Thanks for the replies.

Evil Steve: your 'required reading' cleared ALOT of things up for me! tyvm :)

Ok let me make some statements:
- _T("cheese") = L"cheese" , correct?
- "cheese" is ANSI, L"cheese" is Unicode , correct?
- all 'L' or '_T()' does is convert ANSI to Unicode, correct?


I still am unable to fix my code though, I tried this:
[source lang=cpp]std::wifstream mapData;    mapData.open("normalMap.txt");std::wstring currentLine;std::getline(mapData, currentLine);pGameObj->statusStr = currentLine.c_str();mapData.close();

This DOES compile, but my app crashes immediately. When I break, the cursor jumps to this line:

[source lang=cpp]stdFont->DrawTextW(NULL, text, -1, &rectangle, DT_LEFT, D3DCOLOR_XRGB(255, 255, 255));

I pass 'pGameObj->statusStr' into 'text' (which are LPCTSTR's)
This drawText function worked fine before, I was able to display text.

Any idea whats wrong?

Thanks again.
Quote:Original post by Viperrr
- _T("cheese") = L"cheese" , correct?
Only if your app is building in Unicode mode.

Quote:Original post by Viperrr
- "cheese" is ANSI, L"cheese" is Unicode , correct?
Correct.

Quote:Original post by Viperrr
- all 'L' or '_T()' does is convert ANSI to Unicode, correct?
For static strings known at compile time, yes. You can think of the _T() macro as just prefixing an L to the string in unicode builds, and doing nothing in multi-byte builds.

Quote:Original post by Viperrr
I still am unable to fix my code though, I tried this:
*** Source Snippet Removed ***
This DOES compile, but my app crashes immediately. When I break, the cursor jumps to this line:

*** Source Snippet Removed ***
I pass 'pGameObj->statusStr' into 'text' (which are LPCTSTR's)
This drawText function worked fine before, I was able to display text.

Any idea whats wrong?

Thanks again.
If you look at the debugger (Also required reading), does the value of text look strange? I.e. is it 0xcccccccc, or 0x00000000, or some other pattern? Does it show up correctly in a debug watch window?
This line bothers me
pGameObj->statusStr = currentLine.c_str();

I gather that pGameObj->statusStr is of type LPCTSTR, right?

currentLine.c_str() returns a pointer to where the C string inside currentLine happens to be at the moment. It's okay to pass the c_str() value to a DirectX function or something else that uses the string there-and-then, but it really doesn't help to store the pointer for use later. What happens if, after assigning the pointer to pGameObj->statusStr, the value of currentLine is changed? Then pGameObj->statusStr will be wrong. Either it will point to the new content of currentLine or currentLine's internal C string will have moved and pGameObj->statusStr is now a bad pointer. Also, isn't currentLine a local variable? That's not even going to exist for long.

I'd suggest redefining the pGameObj's type so that statusStr is a std::string, so that you can store strings like this instead:
pGameObj->statusStr = currentLine;

Then pass pGameObj->statusStr.c_str() as the text parameter to when you call that function of yours that calls stdFont->DrawTextW
Thank you Jaywalk! That fixed my problem. It works now :)

This topic is closed to new replies.

Advertisement