tags:

views:

187

answers:

3

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.

+1  A: 

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?

Ruben Bartelink
This doesn't refer to MFC, but to OFC.
kgiannakakis
@kgiannakakis: Didnt follow links or read question, doh. However the reasons are likely to be the same
Ruben Bartelink
@Ruben: Thanks for that. I think I figured it out based on your reply and kgiannakakis's reply.The (this + 1) basically points to the offset into the CString type where the actual content can be found. The mem_alloc statement makes it clearer. This was just a learning exercise. Hence the question.
Vino
Great, ta for 't accept. I +1'd kgiannakakis (for prodding me into improving my answer beyond it's initial state in addition to it being a valid answer that helps you understand what's going on) and you should too IMNSHO :D
Ruben Bartelink
+1  A: 

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));
kgiannakakis
@kgiannakakis: Didnt Looks like a reimpl of MFC's CString, so the reasons why they did it (to make one be able to pass the CString to a `...` in a printf without an explicit cast) stands.
Ruben Bartelink
Okie, the mem_alloc statement makes it clearer. Thanks.
Vino
A: 

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*

Priyank Bolia