views:

244

answers:

3

In my application i'm declaring a string variable near the top of my code to define the name of my window class which I use in my calls to RegisterClassEx, CreateWindowEx etc.. Now, I know that an LPCTSTR is a typedef and will eventually follow down to a TCHAR (well a CHAR or WCHAR depending on whether UNICODE is defined), but I was wondering whether it would be better to use this:

static LPCTSTR szWindowClass = TEXT("MyApp");

Or this:

static const TCHAR szWindowClass[] = TEXT("MyApp");

I personally prefer the use of the LPCTSTR as coming from a JavaScript, PHP, C# background I never really considered declaring a string as an array of chars.

But are there actually any advantages of using one over the other, or does it in fact not even make a difference as to which one I choose?

Thank you, in advanced, for your answers.

+1  A: 

Since Unicode strings are native from Windows NT, unless you want your application to run on ANSI-native Windows 9x, always use wide-character strings (WCHAR or wchar_t types).

Relative to your question, both forms may seem equal; but altough both are expected to be allocated in the constant string section of your executable, string literals are not necessarily modifiable when used as array initializers.

e.g: (from C Faq, 16.6) The following code can crash:

char *p = "HELLO";
p[0] = 'H';

So it's better always to use:

char a[] = "HELLO";

Again, from C Faq: A string literal can be used in two slightly different ways. As an array initializer (as in the declaration of char a[]), it specifies the initial values of the characters in that array. Anywhere else, it turns into an unnamed, static array of characters, which may be stored in read-only memory, which is why you can't safely modify it. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.

http://linuxdude.com/Steve_Sumit/C-faq/q1.32.html

Hernán
Ah, but LPCTSTR is actually a typedef to a CONST CHAR or CONST WCHAR (again depending on whether UNICODE is defined) so szWindowClass[0] = 'H' wouldn't even compile. But thank you for the advice anyway, i think i'll stick with a TCHAR.
Yes, 'H' won't compile with TCHAR if UNICODE is defined.
Hernán
Why wouldn't it compile? Isn't it a widening conversion?
dan04
+3  A: 

The two declarations are not identical. The first creates a pointer, the second an array of TCHAR. The difference might not be apparent, because an array will decompose into a pointer if you try to use it, but you'll notice it instantly if you try to put them into a structure for example.

The equivalent declaration to LPCTSTR is:

static const TCHAR * szWindowClass = TEXT("MyApp");

The "L" in LPCTSTR stands for "Long", which hasn't been relevant since 16-bit Windows programming and can be ignored.

Mark Ransom
What exactly would I notice? A WNDCLASSEX structure, for example, actually takes an LPCTSTR for the lpszClassName member. But there doesn't seem to be a difference when using either TCHAR or LPCTSTR.
If you do a `sizeof` on them you'll see that the pointer is 4 or 8 bytes while the array is 2*(n+1) for a Unicode string of length n.
Mark Ransom
@mrl33t: you should notice that you don't need to do anything special to allocate an array (declared with `[]`) -- you'll never have a dangling pointer. If you use an LPCSTR (a pointer), you'll need to allocate it with `malloc` or assign an existing pointer to it, otherwise it will be a dangling pointer. (You'll also notice in `sizeof()`)
Ken Bloom
A: 

The array form is preferable for string literals of this type. The data and code involved takes up (very, very marginally) less space, and the variable can't be changed to point at a different string. (In fact, there's no variable at all, just a name for the address of the first char in the string -- it behaves very much like a literal value in this respect.)

brone