Blind Challenge: Will this compile?

Pages: 12
Without using your friendly neighborhood compiler, consider this code:
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <Windows.h> //Assume you have a correct windows.h header
#include <limits>

int main()
{
    SetConsoleTitle("My First Program"); //Assume this expands to SetConsoleTitleA
    std::cout << "Hello, World!" << std::endl;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


Do you think this will compile? If not, what do you think causes the error? It should only take you a macrosecond to decide.
Last edited on
Heh, I just fixed a problem exactly like this...
I actually spotted two problems. The one you were looking for and the misuse of SetConsoleTitle (should be SetConsoleTitleA). Whether or not that would cause a compiler error would depend on your settings, though.
Wouldn't compile. Happens to me from time to time :P
Disch wrote:
[...] the misuse of SetConsoleTitle (should be SetConsoleTitleA). Whether or not that would cause a compiler error would depend on your settings, though.
I fixed the first post. With VC++, it's a macro that determines whether to use the A or W version based on whether you're in unicode or not. In this instance assume it's the A version. ;)
Last edited on
I don't have a Windows.h header file so it wouldn't compile for that reason.
Fixed...or rather, clarified.
//Assume you have a correct Windows.h header
Well, that was the only problem I was seeing. If that's not it, then I see nothing wrong with it. Both I and g++ -pedantic (no need to mention the possibility of false positives, thank you) agree that the code is valid.
SPOILER:

Windows.h defines max as a macro, which breaks the call to std::numeric_limits::max. This can be avoided by #defining something before windows.h is included... like NO_MIN_MAX or something -- I forget the exact macro.
closed account (1vRz3TCk)
1
2
#define NOMINMAX
#include <Windows.h> 
There's another problem: cout can't output "Hello, World!" that early in the main. It will output unintelligible nonsense instead. You first need to call sip(coffee); for at least 5 iterations.
Yep, it only took Disch a macrosecond to figure out that is was the max macro. Now, the other question: Why doesn't it break <limits>, which is included after <Windows.h> ? This one I don't actually know the answer to, because when I include my own headers after <Windows.h> they break.
I wasn't sure either, but after testing this is what I discovered (VC2010 Express -- not sure if this is standard or not)

max is defined with parenthesis:

 
#define max(a,b) //... 


So it will only substitute instances of max followed by parenthesis... such as this:

1
2
3
max();  // will be substituted -- but will error because there's not enough params
max(1,2);  // will be substituted correctly
max;  // will not be substituted (no parenthesis) 


With that in mind you can do something like this:

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <windows.h>

int max = 5;  // no parenethesis, so no macro substitution

int main()
{
  std::cout << max;  // OK, no macro sub -- prints "5"
}



With that in mind you can avoid the macro substitution when declaring a function by putting the function name inside parenthesis:

1
2
3
4
int (max)()  // no macro substitution, legal (but weird) function declaration
{
  return 5;
}


This is how limits declares all of these functions.
#undef max in c++config.h included by limits
The proper #include is actually <windows.h>
(That's with a lowercase 'w'.)

I know that Windows filenames are not case-sensitive, but that does not mean that someone's build environment isn't...
closed account (1vRz3TCk)
The proper #include is actually <windows.h>
(That's with a lowercase 'w'.)

Well...in C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include in is Windows.h (That's with a uppercase 'W'.)

I know that Windows filenames are not case-sensitive, but that does not mean that someone's build environment isn't...

This is true but does cause a problem. While I make every effort to ensure the included files are case-sensitive you do get situations like this. Traditionally it was windows.h but currently not* so I go with the current one as that is the one that I am programming against.

* (unless it has changed again)
In MSVStudio2010, the W is uppercase.
Why does it matter whether the 'W' in Windows.h is upper or lowercase when Windows only uses case-insensitive file systems by default? You won't be including Windows.h on Linux...
Once I create Windux, you'll see!
You won't be including Windows.h on Linux
Haven't you ever heard of cross-compilation?
Pages: 12