|
Without that little line, most of your structure is undefined. If you're using a pre-compiled header, might as well include it there. If you're working with an MFC app, you shouldn't need to include it explicitly.
|
|
|
|
|
Good and quick catch, +5
|
|
|
|
|
Hi.
I wrote a simiral question before but I feel like I am still confused.
I am compiling in Unicode and I know that in Unicode circumstance CString is allocated with TCHAR as you see below.
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
So obviously CString has nothing to do with LPCTSTR, which is const char *, or any other type, but TCHAR.
However, when I try to do this code below it occurs an error.
CString _str = TEXT("ABCD");
TCHAR* _tstr = _str;
The correct version of the code above should be like this.
CString _str = TEXT("ABCD");
TCHAR* _tstr = (TCHAR*)(LPCTSTR)_str;
There are two type castings, to LPCTSTR and then to TCHAR*, even though CString is defined with TCHAR type.
I'd like to know why this weird conversion happens from the operator overloading's view of CStringT, and CSimpleStringT and also the template structure of all the classes related to CString.
If I am asking too much to answer in a few sentences, any web pages' link that explain this will be appreciated.
Thanks in advance!
|
|
|
|
|
Dean Seo wrote: CString _str = TEXT("ABCD");
TCHAR* _tstr = _str;
That's not acceptable. _tstr is a pointer to a char (or wchar_t based on your build). But, _str is a CString variable and so, this conversion won't work.
Dean Seo wrote: CString _str = TEXT("ABCD");
TCHAR* _tstr = (TCHAR*)(LPCTSTR)_str;
That's not a good thing to do either. LPCTSTR (with the added C in between means that it's a const ). By explicitly casting it to a TCHAR* , you're casting the const away and then you are assigning it to a TCHAR* later.
Remember that CString is a C++ class. It uses a string (a char* or a wchar_t* ) internally to store the contents, but it does a lot of other things as well. If you really need to acquire a pointer to the location where the class is storing the string, then there's this CString::GetBuffer()[^] method. There are some quirks associated with this method though, and you need to exercise caution while using it. If you call it, you want to make sure that you call CString::ReleaseBuffer()[^] immediately after you're done with the buffer. If you don't know what that means, you don't want to use that method.
I strongly recommend that you read the following essays:
The Complete Guide to C++ Strings, Part I - Win32 Character Encodings[^]
The Complete Guide to C++ Strings, Part II - String Wrapper Classes[^]
CString Management[^]
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Hi, good to see you again.
Rajesh R Subramanian wrote: That's not acceptable. _tstr is a pointer to a char (or wchar_t based on your build). But, _str is a CString variable and so, this conversion won't work.
CString is a class using a wchar_t* to store the contents, and TCHAR is wchar_t.
CSimpleStringT has "operator PCXSTR();", and PCXSTR in Unicode circumstance means LPCWSTR which is also wchar_t*.
So if CSTring uses wchar_t and has a perfect method(operator PCXSTR()) to return wchar_t type,
why can't I get it using TCHAR* (which is also wchar_t*)
I think at least this code below has to work, whether it is safe to use or not.
CString _str = TEXT("ABCD");
TCHAR* _tstr = (TCHAR*)_str;
Thank you for helping me this time again by the way.
|
|
|
|
|
Dean Seo wrote: LPCWSTR which is also wchar_t*.
No, it is not.
LPCWSTR is const wchar_t* and the added "const " has its significance!
Dean Seo wrote: I think at least this code below has to work, whether it is safe to use or not.
CString _str = TEXT("ABCD");
TCHAR* _tstr = (TCHAR*)_str;
That code may compile, but it may or may not work depending on what you intend to do with the _tstr variable. If you use the pointer to modify the contents it's pointing to, then you'll be in trouble, because you promised CString not to modify the contents stored in the pointer that it returned ("const ", remember?).
I'm happy to answer your questions, but before you jump into anything further, I recommend that you read the 3 articles I linked you to, and that will clear up a lot of your doubts.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Rajesh R Subramanian wrote: I recommend that you read the 3 articles I linked you to, and that will clear up a lot of your doubts.
I read those 3 articles all the way through and it did help. Thank you.
I will print out those articles and read again anytime I need.
Rajesh R Subramanian wrote: That code may compile, but it may or may not work depending on what you intend to do with the _tstr variable.
By the way, in that case, the thing is that that code doesn't even comfile and it occurs an 'casting failed' error.
So I just made a simple example that claify why this happens.
class A{
public:
const wchar_t* m_WideCharacter;
operator const wchar_t*() const{
return m_WideCharacter;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A aaa;
wchar_t* _WideCharacter = aaa;
wchar_t* _WideCharacter = (wchar_t*)aaa
wchar_t* _WideCharacter = (wchar_t*)(const wchar_t*)aaa
return 0;
}
I think I just misunderstood how const and operator() that returns const value in C++ works.
To make operator const wchar_t*() const return the value, we definitely need the type casting (const wchar_t*) first, otherwise the compiler wouldn't understand if the operator method in class A can be possibly called.
And that is what (const wchar_t*) is for. That's it.
That is why in that MFC based code I need to write (LPCTSTR*) because CString only has operator PCXSTR(), which is the same as operaotr const wchar_t*(), and the only way that the operator PCXSTR() is called is to write (LPCTSTR*) for type casting.
Am I correct? Or am I not clear enough???
modified on Friday, July 29, 2011 1:52 AM
|
|
|
|
|
Dean Seo wrote: By the way, in that case, the thing is that that code doesn't even comfile and it occurs an 'casting failed' error.
I overlooked it to assume that you did a double casting to take the const away. That is a common thing (a terrible thing, actually) that people do:
CString _str = TEXT("ABCD");
TCHAR* _tstr = (LPTSTR)(LPCTSTR)_str;
Dean Seo wrote: wchar_t* _WideCharacter = (wchar_t*)(const wchar_t*)aaa // works!
You shouldn't say "works!". You should instead say "it compiles!". Yeah, it will compile. But it's a terrible thing to do. How about this instead?
A aaa;
const wchar_t* p = aaa;
There are several APIs (and functions that we may code) that will need a read-only string. For example, you may write a function that takes the path of a file and encrypts it. So, you'll just be accepting the string which will be the path, and you'll not be modifying the string itself. In cases like that (and in MOST cases), you will only need a read-only string. That's why CString gives you a LPCTSTR (const wchar_t* ), which will be pointing to the internal buffer where CString is storing the string.
But there are those edge cases where might want to have direct write access to the internal buffer of CString . For such cases, CString provides the GetBuffer() method (which I already explained).
Conclusively, there is no excuse for abusing the LPCTSTR operator (using it to cast the const away and assigning it to a non-const variable is bad).
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Dean, let me know if you need any further explanation.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
I am sorry for this late response.
Thank you for helping me. You are the best!
Thank you again.
|
|
|
|
|
You're welcome.
Dean Seo wrote: You are the best!
Now, you're overselling me.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Hi,
In samp.h I have a struct definied as
struct X_PStruct;
typedef struct X_PStruct *X_P;
struct X_PStruct{
...
}
In samp.c
#include"samp.h"
void func1()
{
X_P p = Create (NULL);
....
}
In func1 whereever I try to use p, it creates an error "C2065: p undeclared identifier"
What am I doing wrong?
Thanks.
|
|
|
|
|
Member 8117171 wrote: In func1 whereever I try to use p, it creates an error "C2065: p
undeclared identifier" What am I doing wrong?
I tried to replicate this but could not. It always compiles fine.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather
|
|
|
|
|
I use the VS2010. Although I created the project as Win32 Console, and for each .c file I have the properties set to compile as c code. Is there some setting that I am missing?
|
|
|
|
|
I used VS6. I'm not sure if the VS2010 compiler, given that it's stricter, would be a factor.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather
|
|
|
|
|
No, there's nothing in that C code that is non-standard. If I had to guess, he's just missing something silly like a semicolon/closing bracket or something like that.
|
|
|
|
|
I tried with VS2008 and it worked.
Watched code never compiles.
|
|
|
|
|
did you forget to add a ";" at the end of the struct ?
struct X_PStruct;
typedef struct X_PStruct *X_P;
struct X_PStruct{
...
};
Watched code never compiles.
|
|
|
|
|
Did you remember to end your struct definition with a ';'? Also, there's a shorthand method to declaring structs like that:
typedef struct _X_PStruct{
...
} X_PStruct, *X_P;
X_PStruct MyStruct;
X_P pMyStruct;
One last thing, there's nothing called Create() that you can call like that (at least that I remember ).
|
|
|
|
|
Sorry, that was typo that I left ";" when I was typing this question. Create() is a function that I created that has a return type struct X_Pstruct
|
|
|
|
|
Oh ok, that makes more sense...
|
|
|
|
|
Post the line of code where the error occurs.
Post the entire func1 if possible.
Are there any other errors or warning before the line that you mention?
|
|
|
|
|
Hello All
I know signed on user name and i provide the user an edit box to enter the corresponding password.
Now is there a way to validate it?
Regards
|
|
|
|
|
Take a look at the LogonUser()[^] API.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|