Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Is CString really based on TCHAR?

Is CString really based on TCHAR?

Scheduled Pinned Locked Moved C / C++ / MFC
questionc++helpannouncement
9 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dean Seo
    wrote on last edited by
    #1

    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!

    R 1 Reply Last reply
    0
    • D Dean Seo

      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!

      R Offline
      R Offline
      Rajesh R Subramanian
      wrote on last edited by
      #2

      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. LP**C**TSTR (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[^]

      D 1 Reply Last reply
      0
      • R Rajesh R Subramanian

        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. LP**C**TSTR (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[^]

        D Offline
        D Offline
        Dean Seo
        wrote on last edited by
        #3

        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.

        R 1 Reply Last reply
        0
        • D Dean Seo

          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.

          R Offline
          R Offline
          Rajesh R Subramanian
          wrote on last edited by
          #4

          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.

          D 1 Reply Last reply
          0
          • R Rajesh R Subramanian

            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.

            D Offline
            D Offline
            Dean Seo
            wrote on last edited by
            #5

            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:
            // I didn't allocate any block of memory on m_WideCharacter to make it simpler.
            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; // error-the operator method can't be called.
            wchar_t* _WideCharacter = (wchar_t*)aaa // error-the operator method can't be called.
            wchar_t* _WideCharacter = (wchar_t*)(const wchar_t*)aaa // works!
            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

            R 2 Replies Last reply
            0
            • D Dean Seo

              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:
              // I didn't allocate any block of memory on m_WideCharacter to make it simpler.
              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; // error-the operator method can't be called.
              wchar_t* _WideCharacter = (wchar_t*)aaa // error-the operator method can't be called.
              wchar_t* _WideCharacter = (wchar_t*)(const wchar_t*)aaa // works!
              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

              R Offline
              R Offline
              Rajesh R Subramanian
              wrote on last edited by
              #6

              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; //Using the LPCTSTR operator to get the pointer, and then casting the const away. A bad thing to do.

              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.

              1 Reply Last reply
              0
              • D Dean Seo

                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:
                // I didn't allocate any block of memory on m_WideCharacter to make it simpler.
                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; // error-the operator method can't be called.
                wchar_t* _WideCharacter = (wchar_t*)aaa // error-the operator method can't be called.
                wchar_t* _WideCharacter = (wchar_t*)(const wchar_t*)aaa // works!
                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

                R Offline
                R Offline
                Rajesh R Subramanian
                wrote on last edited by
                #7

                Dean, let me know if you need any further explanation.

                "Real men drive manual transmission" - Rajesh.

                D 1 Reply Last reply
                0
                • R Rajesh R Subramanian

                  Dean, let me know if you need any further explanation.

                  "Real men drive manual transmission" - Rajesh.

                  D Offline
                  D Offline
                  Dean Seo
                  wrote on last edited by
                  #8

                  I am sorry for this late response. Thank you for helping me. You are the best! Thank you again.

                  R 1 Reply Last reply
                  0
                  • D Dean Seo

                    I am sorry for this late response. Thank you for helping me. You are the best! Thank you again.

                    R Offline
                    R Offline
                    Rajesh R Subramanian
                    wrote on last edited by
                    #9

                    You're welcome.

                    Dean Seo wrote:

                    You are the best!

                    Now, you're overselling me. :-O

                    "Real men drive manual transmission" - Rajesh.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups