4

This is the first code

#include <stdio.h>
#include <conio.h>
int main()
{
    int small;//showing error-(two or more data type in declaration specifiers
}

This is the second code

#include <stdio.h>
int main()
{
    int small;//normal declaration without any error
}

Whenever I include header file <conio.h> then declaring a identifier "small" gives an error, why? I am using mingw gcc compiler and codeblocks ide

Also I have added following code in <conio.h>

#include <windows.h>
void gotoxy(short int col,short int row)
{
    HANDLE hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
    COORD position={col,row};
    SetConsoleCursorPosition(hStdout,position);
}

after removing above code from <conio.h>

int small;

works even after including <conio.h>.

haccks
  • 104,019
  • 25
  • 176
  • 264

7 Answers7

8

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.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
4

No. There is no keyword like small in standard C. This may be a macro in <conio.h>.

C11: 6.4.1 Keywords:

keyword: one of

auto 
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
inline
int
long
register
restrict
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
_Alignas
_Alignof
_Atomic
_Bool
_Complex
_Generic
_Imaginary
_Noreturn
_Static_assert
_Thread_local
haccks
  • 104,019
  • 25
  • 176
  • 264
2

I found it... its a macro defined in some header file which is included in windows.h.

as i have included windows.h in conio.h so in my program it is automatically included when i include conio.h.

I Found it by ctrl + clicking on small

0

There is no such keyword, but check if it is typedefed somewhere.

Pang
  • 9,564
  • 146
  • 81
  • 122
Pranit Kothari
  • 9,721
  • 10
  • 61
  • 137
  • 2
    It doesn't matter if it's `typedef`ed. If it were, the declaration `int small;` in an inner scope would be perfectly legal, and would hide the `typedef`. It's more likely to be a macro. – Keith Thompson Jan 16 '14 at 16:02
0

The error seems to be the fault of MinGW. The same error appears with large.

Pang
  • 9,564
  • 146
  • 81
  • 122
Daniele
  • 821
  • 7
  • 18
0

By adding #include <windows.h>, you are pulling in a lot of other header files. One problem that has been reported is of it defining a preprocessor macro "small". It has also been discussed in another SO question.

One workaround is to add #undef small after you #include <windows.h>.

Community
  • 1
  • 1
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
0

Just define WIN32_LEAN_AND_MEAN macro in code or VS Properties dialog and the problem will be gone:

#define WIN32_LEAN_AND_MEAN
Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
def
  • 521
  • 4
  • 16