Or in other words, awesome C an C++ language features you’ll learn to love in GCC, that’ll break your heart if you ever have to use Visual Studio. ๐Ÿ˜‰

This is a list I collected whilst getting my Smiles PC code to compile with Visual Studio 2008. Most have no equivalent in Visual Studio, but one simply has a slightly different syntax (compatible too).

As before, long and technical. Hit the link if you’re up for the challenge. You’ve been warned. ๐Ÿ˜€

Determining if it’s Visual Studio

Generally speaking, you can check for the symbol _MSC_VER. If it exists it’s Visual Studio, otherwise it’s probably GCC. From what I’ve seen, all the non GCC’s are pretty good at identifying themselves (__MWERKS__, __ARMCC_VERSION, etc).

Variadic Macros

In GCC, you can wrap printf and similar functions as follows.

#define Log( args... ) \
        printf( args )

Visual Studio 2008 has a slightly different syntax. To Visual Studio’s credit, this is part of the C99 standard.

#define Log( ... ) \
        printf( __VA_ARGS__ )

Recent versions of GCC support the __VA_ARGS\__ syntax as well. My guess is it’s the 2.9.x and earlier series that doesn’t, but I’ve not looked in to it.

An alternate usage can be used to make โ€œ…โ€ and __VA_ARGS\__ work as zero arguments.

#define Log( message, ... ) \
        printf( "Log: " message, ## __VA_ARGS__ )

The ## syntax can be used with GCC’s โ€œargs…โ€ variation too.

Case ranges in switch statements

Once you’ve tried it, you wont want to go back. On GCC you can define a range as follows:

case ST_PAGES ... ST_PAGES_MAX:
case 'A' ... 'Z':
case 1 ... 5:

My โ€œsolutionโ€ has been to create a macro for when you know how many there are.

#define case3( _var ) \
	case (_var) + 0: \
	case (_var) + 1: \
	case (_var) + 2:

And yes, there’s a lot of those. The number in the name says how many to make. This is hardly a perfect solution, as range ambiguity makes the code easier to write.

Array Initializers in Constructors

If a class contained an array of something, wouldn’t it be nice to be able to initialize it? GCC thinks so.

inline Matrix2x2( const Vector2D& _v1, const Vector2D& _v2 ) :
	Array( (Real[]) { 
		_v1.x, _v1.y,
		_v2.x, _v2.y
		} )
{
}

(Lets ignore intrinsics being better for a moment, okay?)

Visual Studio, not so much. The alternative is not to use an initializer list.

inline Matrix2x2( const Vector2D& _v1, const Vector2D& _v2 )
{
	Array[0] = _v1.x;
	Array[1] = _v1.y;
	Array[2] = _v2.x;
	Array[3] = _v2.y;
}

The problem with this is if type of the array has a constructor, then it’s going to call the default constructor for the initializer list stage, then the copy constructor for the assignments above. Theoretically, this example should be an easy optimization to catch (2 assignments without an access in between), so you can always hope the optimizer catches it. But it shouldn’t be much work to create a case it wont.

Variable and zero sized arrays

This feature of GCC I love.

Allocating memory off the stack is extremely fast, and almost guaranteed to be consistent. After all, it’s implemented by a mere change of the stack pointer register. Using local variables is the normal way to do this. With this GCC extension, you can use variables or math to dynamically allocate off the stack. It can be scoped too, to control when the memory is allocated.

void MyVetexFunc( const size_t VertexCount ) {
	float Verts[ VertexCount << 1 ];
	...
}

Visual Studio can’t do that. I need to waste my time allocating off the heap, and cleaning up when I’m done.

void MyVertexFunc( const size_t VertexCount ) {
	float* Verts = new float[ VertexCount << 1 ];
	...
	delete [] Verts;
}

This can be especially terrible for small blocks of code that, during normal use, only use a handfull of bytes. 2-3 floats worth, or such.

Moving on

For the most part, those were the changes I had to make to the code for it to run. There were a couple #pragmas I needed to add too, to shut up some 1200 warnings I was triggering.

There were only a few outright code changes required. The first was flipping my slashes, “/” to “", as expected of the Windows world. In addition, my directory searching code had to be rewritten. It’s noticeably slower than my MinGW equivalent, so there may be something I can do to improve that. Finally, I had to upgrade LZMA, since I guess the version I was using had issues with Visual Studio 2008.

Lo and behold, Smiles built in Visual Studio 2008.

After a less than thrilling couple days, I’m certainly Smiling

And now that additional compiler compatibility hurdle is behind me. ๐Ÿ˜‰