C & C++ Language Tricks





2.00/5 (7 votes)
Mar 4, 2000

87212
More tricks of use to a programmer who shuns run-time libraries.
Introduction
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.
Playing with the C stack
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);
}
Constructing variable length structs
A trick to using structs that have a variable sized member is to use an overloaded operator
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)]; ...
Working with big endian data
A have always favored little endian number representation over big-endian, which why I was saddened when 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:
- If a
typedef unsigned short
was used you could accidently use the number in situations without converting it. - The operator
unsigned short
ensures that the struct can be used as a normal unsigned short where required.
Please send any comments or bug reports to me via email. For any updates to this article, check my site here.