I guarantee that small
is not a keyword in C. If it were, the presence or absence of a #include
directive would not make any difference.
The problem is that <windows.h>
stupidly defines small
as a macro. (Other answers and comments suggest it might be a typedef
, but that wouldn't explain the problem you're seeing.)
I'm able to reproduce the problem on my system (Cygwin, Windows 7, compiling with mingw32-gcc
, which is installed as part of the Cygwin package). Presumably the same thing would happen with MinGW installed separately from Cygwin.
First of all, <conio.h>
is a (non-standard) header provided by the implementation. You almost certainly shouldn't be trying to modify it. You definitely shouldn't be adding a function definition to a header file (function definitions belong in .c
files, not in .h
files). If you want to write your own gotoxy
function, declare it in your own header and define it in your own .c
file; don't mess around with the implementation. (B
But when you added your gotoxy
function to <conio.h>
, you also added
#include <windows.h>
Here's a small program that illustrates the problem:
#include <windows.h>
int main()
{
int small;
}
When I compile this with mingw32-gcc
, I get:
c.c: In function 'main':
c.c:4:9: error: two or more data types in declaration specifiers
c.c:4:5: warning: useless type name in empty declaration [enabled by default]
Digging further, it turns out that <windows.h>
includes <rpcndr.h>
, which contains the following:
#define small char
So every occurrence of the identifier small
in any C source that has #include <windows.h>
will be replaced by the keyword char
-- which, in your case, will cause a syntax error.
A handy way to find things like this: gcc
has a -E
option that causes it to show the output of the compiler's preprocessor phase. With the above program, I tried this:
$ mingw32-gcc -E c.c | tail
#pragma pack(pop)
# 115 "c:\\gnustep\\bin\\../lib/gcc/mingw32/4.6.1/../../../../include/windows.h" 2 3
# 2 "c.c" 2
int main()
{
int char;
}
$
which shows how the int short;
declaration was mangled by the preprocessor.
To be clear, this is entirely the fault of the maintainers of <windows.h>
and <rpcndr.h>
. small
is a perfectly valid C identifier, and a system header absolutely should not define it as a macro. typedef char small;
would have served the same purpose and not caused this problem. Others have had similar problems with <windows.h>
defining macros min
and max
. That can be worked around with:
#define NOMINMAX
#include <windows.h>
but as far as I can tell there's no such workaround for small
.
Incidentally, rpcndr.h
also defines hyper
.
The simplest solution is to call your variable something other than small
-- and hope you don't collide with other macros defined in <windows.h>
. Or you can add
#undef small
before the declaration. You shouldn't need to do either of these things, but thanks to poorly written system headers, such workaround are sometimes necessary.
Or just avoid including <windows.h>
(that's not always possible).
(You could modify your copy of the rpcndr.h
file, but I advise against doing so; it's likely to cause other problems, and your code still won't compile on a system where rpcndr.h
hasn't been hacked.)
UPDATE : This may have been corrected. I don't see the error using x86_64-w64-mingw32-gcc
under Cygwin on Windows 10. Perhaps someone else who uses mingw can investigate further.