The material I'm going to present may be pertinent to the discussion. For the past two years I've been converting my 'mission critical' enterprise software from PowerBASIC to C++. We're talking several hundred thousand lines of pure SDK Win32 Api code. My intent has been to be able to create x86/x64 code compileable with both Microsoft VC++ and GNU GCC. I'm only doing wide character builds.
In a nutshell, it hasn't been that hard to do, but unlike most here at this site probably, I'm old and pretty much know what I'm doing (its the old part that is pretty much unlike others here - not that you don't know what you are doing). I started coding on mainframe computers back in the mid 70s. Used various versions of BASIC back in the 80s and 90s; taught myself C and C++ during the 90s. Since 2000 I've mostly used C/C++ for Windows CE coding, and PowerBASIC SDK code for desktop/laptop Windows use. Now for the particulars.
This very simple program won't compile with VC9...
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
// g++ Ar1.cpp -oAr1_x64.exe -mconsole -m64 -s -Os // < x64
// cl Main.cpp
#include <cstdio>
int main(void)
{
int x,y;
y=3, x=4;
int iAr[y][x];
getchar();
return 0;
}
|
Other day I downloaded the Windows 7 SDK which is VC10 maybe? But hadn't tested with that yet (not on this computer). But either in the IDE or command line compiling it won't work. Here are the error messages...
1 2 3 4 5 6 7 8 9 10 11
|
C:\Code\VStudio\VC++9\MultiDimArray\MultiDimArray>cl Main.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
Main.cpp
Main.cpp(9) : error C2057: expected constant expression
Main.cpp(9) : error C2466: cannot allocate an array of constant size 0
Main.cpp(9) : error C2057: expected constant expression
Main.cpp(9) : error C2466: cannot allocate an array of constant size 0
Main.cpp(9) : error C2087: 'iAr' : missing subscript
Main.cpp(9) : error C2133: 'iAr' : unknown size
|
The bare C++ language of course has very, very poor dynamic multi-dimensional array capabilities. If one can get past the horrible syntax, the C++ Std. Lib. has the capabilities to handle this stuff.
On the other hand, that program above compiles and runs fine in any version of GCC C++ I have. So in that one instance GCC comes out a bit in front of MS VC++.
Moving on, consider this ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <cstdio>
#include "Strings.h"
int main()
{
String s1,s2;
s1 = L"iNumber = " + Str(123456789);
wprintf(L"%s\n",s1.lpStr());
getchar();
return 0;
}
|
This ...
String
...is my String Class - not the one in the C++ Std. Lib. As might be typical, my String class has a lot of constructors, and I handle conversions of numbers in binary format to strings through operator= calls or constructors. This ...
Str(123456789);
...is simply a function call that returns a String (my String Class - not shown). This is the function ...
1 2 3 4
|
String Str(int iNum)
{
return iNum;
}
|
That operates through the return statement calling one of my overloaded String constructors as such ...
1 2 3 4 5 6
|
String::String(int iNum)
{
this->lpBuffer=new TCHAR[16];
this->iCapacity=15;
this->iLen=_stprintf(this->lpBuffer,_T("%d"),iNum);
}
|
... so this ...
s1 = L"iNumber = " + Str(123456789);
...is simply a line to assign a string literal plus a function that returns one of my String Objects to another one of my String Objects. The result of course should be ...
VC9 does it without a whimper. GCC refuses to compile it. Says it can't resolve operator+ call.
So you see the way these things can go. Each compiler is just a bit different. They are very highly compatible. I'd say like 99.99999% compatible. But you will come across differences. In my large code conversion projects I'm handling the slight differences through conditional compilation statements. Pertaining to these two compilers I've found I can get by with just two, which I have defined like so...
1 2
|
#define VSTUDIO
#define NEW_GCC
|
What the VSTUDIO define is used for is that GCC doesn't seem to know anything about High DPI (Dots Per Inch) coding - at least up to the 4.8 series compilers. I know 4.9 came out fairly recently, but I haven't gotten around to trying that yet. SetProcessDPIAware() and IsProcessDPIAware(), as well as some others were added to the Api with VC9 and Vista. These calls are not present on Win 2000/XP, so to use my code on those OSs I use the typical LoadLibrary()/GetProcAddress() call sequence. So that's what the VSTUDIO define is mostly used for (although it is used for something else on another one of my apps).
On GCC these calls do not seem to exist. At least they are not declared in winuser.h Perhaps I could get it to work if I simply declared the function. I really don't know how the MinGW organization came by their libs. Maybe somebody very knowledgable like kbw or disch could enlighten me on that. All I can say for sure is that the function calls won't compile, and if the High DPI Aware setting is put in the manifest it has no effect. So I guess that's another plus in favor of MS VC++.
In terms of my need for 'NEW_GCC', that seems to be a POSIX compliance thing, which I believe is an unresolved issue for MinGW. And its really dumb and is the single biggest nuisance in organizing my code to be compilable by both VC and GCC. Here's an example from one of my apps ...
1 2 3 4 5 6 7 8 9 10 11 12
|
#ifdef MyDebug
fprintf(fp," Sql.ODBCConnect() Succeeded!\n");
fprintf(fp," hMain = %p\n",hMain);
fprintf(fp," pDBPaths = %p\n",pDBPaths);
#ifdef NEW_GCC
fwprintf(fp,L" pDBPaths->ActiveDB.szDescriptor = %S\n",pDBPaths->ActiveDB.szDescriptor);
fwprintf(fp,L" strDate = %S\n",strDate.lpStr());
#else
fwprintf(fp,L" pDBPaths->ActiveDB.szDescriptor = %s\n",pDBPaths->ActiveDB.szDescriptor);
fwprintf(fp,L" strDate = %s\n",strDate.lpStr());
#endif
#endif
|
You can stare at that and stare at it and not likely see what the difference is. Its a real nuisance! In wide character compiles GCC wants a capital 'S' in printf family functions as the format specifier where character strings are output. And it wants a small 's' for ansi output! VC doesn't seem to care much. And the even wierder thing is it only applies to the newer GCC compilers. The older ones like the 4.4 series behave like VC in this - they don't care! So for the newer GCC builds I have to uncomment my 'NEW_GCC' #define.
I get a kick out of Disch. He's a holder of strong opinions. Like his one that anybody who tries to do C++ coding without a debugger is insane or a masochist. I guess that's me because the last time I used stepping debuggers is when I was teaching myself assembler coding ages ago. Its not that I have anything against them. Its just that I do a lot of database related work with tables of values and a trace/output log file seems to work better for me in showing tabular values and the history of how I got to where I'm at in the code. I'd also have to say that for many of the types of data entry/editor type applications I've done over the years debuggers simply didn't work well.
continued...