CString : What does (TCHAR*)(this + 1) mean?

642 views Asked by At

In the CString header file (be it Microsoft's or Open Foundation Classes - http://www.koders.com/cpp/fid035C2F57DD64DBF54840B7C00EA7105DFDAA0EBD.aspx#L77 ), there is the following code snippet

struct CStringData
{   
    long nRefs;
    int nDataLength;
    int nAllocLength;
    TCHAR* data() { return (TCHAR*)(&this[1]); };
    ...
};

What does the (TCHAR*)(&this[1]) indicate?

The CStringData struct is used in the CString class (http :// www.koders.com/cpp/fid100CC41B9D5E1056ED98FA36228968320362C4C1.aspx).

Any help is appreciated.

3

There are 3 answers

4
Ruben Bartelink On BEST ANSWER

CString has lots of internal tricks which make it look like a normal string when passed e.g. to printf functions, despite actually being a class - without having to cast it to LPCTSTR in the argument list, e.g., in the case of varargs (...) in e.g. a printf. Thus trying to understand a single individual trick or function in the CString implementation is bad news. (The data function is an internal function which gets the 'real' buffer associated with the string.)

There's a book, MFC Internals that goes into it, and IIRC the Blaszczak book might touch it.

EDIT: As for what the expression actually translates to in terms of raw C++:-

TCHAR* data() { return (TCHAR*)(&this[1]); };

this says "pretend you're actually the first entry in an array of items allocated together. Now, the second item isnt actually a CString, it's a normal NUL terminated buffer of either Unicode or normal characters - i.e., an LPTSTR".

Another way of expressing the same thing is:

TCHAR* data() { return (TCHAR*)(this + 1); };

When you add 1 to a pointer to T, you actually add 1* sizeof T in terms of a raw memory address. So if one has a CString located at 0x00000010 with sizeof(CString) = 4, data will return a pointer to a NUL terminated array of chars buffer starting at 0x00000014

But just understanding this one thing out of context isnt necessarily a good idea.

Why do you need to know?

1
kgiannakakis On

It returns the memory area that is immediately after the CStringData structure as an array of TCHAR characters.

You can understand why they are doing this if you look at the CString.cpp file:

static const struct {
    CStringData data;
    TCHAR ch;
} str_empty = {{-1, 0, 0}, 0};

CStringData* pData = (CStringData*)mem_alloc(sizeof(CStringData) + size*sizeof(TCHAR));
0
Priyank Bolia On

They do this trick, so that CString looks like a normal data buffer, and when you ask for the getdata it skips the CStringData structure and points directly to the real data buffer like char*