Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

What's the merit of mass including windows headers for their typedefs? 2

Status
Not open for further replies.

jjjkkk77

Programmer
Jun 14, 2007
10
US
Hi pros,

Recently I have been reworking a c++ project from a commercial software company.

I found they do the following a lot in their code:

include winThis.h, winThat.h, winBlah.h etc. etc. and in the end their code only end up using some simple typedefs in these windows headers, e.g. #define unsigned long ULONG

I think first of all this slows down the compilation, as you include so much stuff that you do not use at all, right?

Secondly, it makes the code a pain in ass to carry over different environments: 1. different OS and hence different windows headers 2. different versions of Visual Studio seem to process headers of the same project in different way too

So, why not just use "unsigned long" yourself instead of using ULONG from a environment-dependent system header?
 
Should't have been a #define. Should have been
Code:
typedef unsigned long ULONG;
The problem comes when people start using things like __int64 and TCHAR. If you are working on VS6, __int64 is 8 bytes and TCHAR is 2 bytes, which some code as unsigned short and others as wchar_t.

On VS 2003, it is preferable to use long long instead of __int64.

On Unix, __int64 doesn't exist so you have to use long long. wchar_t is 4 bytes. If you use typedefs, you only need to modify one file.

I normally don't bother with MS specific pragma once and just use #ifndef, #define, #endif in my headers. Works on every OS and every OS will process it the same way.

The slowing down is negligible unless you're using a 20 year old disk on a 33MHz 286. A 1GHz system can build a 10000 line program (source + headers) in less than 1 second.
 
Microsoft threw anything & everything into windows.h and kept adding new types without even checking if another developer already added a similar one... Eventually they ended up with the mess known as windows.h. Since they have to maintain backwards compatability, they can't easily fix the mistakes there, and we are stuck with it. Even worse is the fact that they define a ton of macros in there which conflict with a lot of standard names (min & max for example).
I think they should definitely spend some time cleaning up that mess!
 
Thanks xwb and cpjust

xwb you said 'If you use typedefs, you only need to modify one file.'. So is it your practice to place all your project's typedefs in one header file?
 
Only the platform dependent ones. I also use typedefs to save typing. For instance,
Code:
typedef std::list<UIFieldList::iterator> FLIterList;
typedef FLIterList::iterator             FLIterIter;
Something like that wouldn't be in the header file for platform dependent typedefs.

Some places use typedefs for structure/enum/unions. This makes programming in C a bit neater but is totally unnecessary in C++. If you see that sort of coding, you know the person who has decided that that will be the standard is really a C programmer and can't shake off a bad habit.
 
So what do you do with the platform dependent typedefs? Do you just do what I showed in the opening post? Wouldn't that make your code not portable? Thanks.
 
The platform dependent typedefs are tuned to the specified platform. It is portable enough in that it is the only file you need to consider when moving from one platform to another. One I had to do recently was 64-bit integers. It went along the lines of
Code:
// I had to define VS6 on the compile line
#ifdef VS6
typedef __int64 LONGLONG;
#define LL(x) x##i64
#else
typedef long long LONGLONG;
#define LL(x) x##LL;
#endif
So all the other bits just used something like
Code:
LONGLONG llewellyn = LL(123456789012345);
What takes time is working out how things are represented on the different platforms. Took me over 2 hours to find out how 64 bit integers were represented on VS6. Once the platform bits are in, it just builds and you only have to change code once.

The most frustrating thing I find with all this is the definitions of boolean logic.

C++ has bool, true and false
gcc has _Bool and bool (typedef _Bool), true and false
MS has BOOL (typedef int), TRUE and FALSE
X-Windows has Bool (typedef char), True and False

There are loads of warnings whenever the wrong type is tested for. It goes against the grain but to get rid of warnings without casting, you end up with coding like
Code:
bool doit = (x == True);
Beware of casting when you deal with multi-platform code. It hides a multitude of sins.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top