This document is a collection of some of the interesting constructs that are possible in C and C++. While "nice" these features may not serve to increase code clarity but to obfuscate it. Your mileage may vary.
Parameters on the stack appear in memory with the leftmost item at the lowest memory location. Thus you can get a pointer to your functions stack frame, and walk the parameter list, or even cast your stackframe to a struct that can be passed to other functions.
The first sample demonstrates how to retrieve the pointer to any variable parameters passed to the function.
int __cdecl printf(char const* pszFmt,...)
{
char buf[1024];
return wvsprintf(buf,pszFmt,&pszFmt+1);
}
This sample demonstrates how the functions passed to a function can be passed to another function.
BOOL InvalidateRect(
HWND hwnd,
LONG left,
LONG top,
LONG right,
LONG bottom,
BOOL fErase)
{
return InvalidateRect(hwnd,(LPRECT)&left,fErase);
}
A trick to using structs that have a variable sized member is to use an overloaded operator new to allocate space for the struct.
struct string {
int cb; // a data member
char sz[]; // the string data
void* operator new(int cb, int cbExtra){
return new char[cb+cbExtra];
}
};
Now contrast the following code to create such a struct:
...
string* pStr = new(strlen(pszInString)) string;
...
The "C" method of working with variable sized looks like this
...
string* = (string*)new char[sizeof(string) + strlen(pszInString)];
...
A have always favored little endian number representation over big-endian, which why I was saddened whn I found that TCP/IP, and most internet protocols (such as SSL3) use a big endian representation for numbers. Following is the type of construct I use when I need to work with a non-native data type in structs that I pull off of the network.
typedef unsigned char uint8;
struct uint16 {
uint8 n[2];
operator unsigned short(){
return ((unsigned short)n[0] << 8) + n[1];
}
};
Using a struct like this has two advantages: