“small”是C语言中的关键字吗?

4

这是第一行代码

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

这是第二段代码

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

每当我包含头文件<conio.h>时,声明标识符“small”就会出错,为什么? 我正在使用mingw gcc编译器和codeblocks集成开发环境。
此外,我已经在<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);
}

<conio.h>中删除上述代码后:
int small;

即使包含了<conio.h>,它仍然可以正常工作。

4
不,但它可能是您的conio.h中的typedef或#define。为什么不去看一下呢? - Roddy
我已经编辑了代码,请再次查看。 - user3180902
2
也许这个很相关:http://bugs.python.org/issue14387 - Fred Larson
你用的是哪个集成开发环境?既然你包含了 conio.h,那么很可能你已经安装了VS,但CodeBlocks或实际上大多数IDE都允许你使用Ctrl + 单击单词以查看其定义…… - Elias Van Ootegem
1
一个 typedef 不会引起这个问题,只有宏会。 - Keith Thompson
显示剩余5条评论
7个回答

8
我保证在C语言中small不是关键字,如果是关键字,在有或无#include指令的情况下都不会有任何区别。
问题在于<windows.h>愚蠢地将small定义为宏。 (其他答案和评论表明它可能是typedef,但这并不能解释您看到的问题。)
我能够在我的系统上(Cygwin、Windows 7,使用mingw32-gcc编译,它作为Cygwin包的一部分安装)重现问题。假定从Cygwin单独安装MinGW也会发生同样的事情。
首先,<conio.h>是一个(非标准)由实现提供的头文件。你几乎肯定不应该尝试修改它。你绝对不应该在头文件中添加函数定义(函数定义应该放在.c文件中,而不是.h文件中)。如果你想编写自己的gotoxy函数,请在你自己的头文件中声明它,并在你自己的.c文件中定义它;不要玩弄实现。(B
但当你将你的gotoxy函数添加到<conio.h>时,你也添加了
#include <windows.h>

这是一个小程序,用于说明问题:
#include <windows.h>
int main()
{
    int small;
}

当我使用mingw32-gcc编译此程序时,会出现以下错误:
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]

深入研究后,发现<windows.h>包括<rpcndr.h>,其中包含以下内容:
#define small char

在任何使用了#include <windows.h>的C源代码中,标识符small的每个出现都将被关键字char替换——在您的情况下,这将导致语法错误。一个方便的方法是使用gcc-E选项,它可以显示编译器预处理阶段的输出。对于上面的程序,我尝试了这个选项。
$ 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;
}
$ 

这段代码展示了预处理器如何破坏了int short;的声明。

需要明确的是,这完全是<windows.h><rpcndr.h>维护人员的责任。 small是一个完全有效的C标识符,系统头文件绝对不应将其定义为宏。 typedef char small;可以达到相同的目的,而不会导致这个问题。其他人也遇到了类似的问题,例如 使用<windows.h>时定义宏minmax。这可以通过以下方式解决:

#define NOMINMAX
#include <windows.h>

据我所知,small 目前没有类似的解决方法。

顺便提一下,rpcndr.h 还定义了 hyper

最简单的解决方法是将变量命名为除 small 以外的其他名称,并希望不会与在 <windows.h> 中定义的其他宏发生冲突。或者您可以添加

#undef small

在声明之前,你不应该做这两件事情。但由于系统头文件编写不好的原因,有时候需要这样做来解决问题。如果可能的话,最好避免包含<windows.h>。你可以修改rpcndr.h文件,但我建议不要这样做;这很可能会导致其他问题,并且你的代码仍然无法在没有被篡改的rpcndr.h的系统上编译。更新:这个问题可能已经被修复了。我在Windows 10下的Cygwin上使用x86_64-w64-mingw32-gcc时没有看到错误。也许其他使用mingw的人可以进一步调查。

不错的“简短”回答。不能完全归咎于<windows.h>维护者的错误。 - chux - Reinstate Monica
为了避免包含 windows.h,可以为所需的函数创建一个包装器,然后在该模块中只包含 windows.h - phuclv

4

不可以。在标准C中没有像 small 这样的关键字。这可能是 <conio.h> 中的宏。

C11:6.4.1 关键字:

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

它也可以在头文件中定义#include,该头文件为conio.h而不是stdio.h - Jongware
@haccks:这个查询有没有任何解释? - user3180902
我不理解你回答中新增的部分。 - haccks
我只是在问是否有关于上述查询的任何解释。 - user3180902
我知識有限,無法確定上述查詢是否存在任何解釋。 - haccks

2
我发现这是一个宏,在一些头文件中定义,这些头文件被包含在windows.h中。
因为我已经在conio.h中包含了windows.h,所以当我包含conio.h时,它会自动包含。
我通过按ctrl + 单击small找到了它。

0

只需在代码或VS属性对话框中定义WIN32_LEAN_AND_MEAN宏,问题就会消失:

#define WIN32_LEAN_AND_MEAN

0

没有这样的关键字,但请检查是否在某个地方进行了typedef


2
无论它是否被typedef,如果是的话,在内部作用域中声明int small;将是完全合法的,并且会隐藏typedef。更可能的是它是一个宏。 - Keith Thompson

0

错误似乎是 MinGW 的问题。使用large时出现了相同的错误。


我正在阅读这里:http://www.gecode.org/pipermail/users/2013-January/003763.html - Daniele
"Int "large"被修改为"large_",纯粹是出于美观的考虑。" - Daniele
conio.h 中删除 void gotoxy() 后,int small; 可以正常工作。 - user3180902
@learner:如果你使用#include <windows.h>,你仍然会遇到同样的问题。而且conio.h是由你的实现提供的,你不应该修改它。 - Keith Thompson

0
通过添加#include <windows.h>,您会引入许多其他头文件。 已报告的一个问题 是它定义了预处理器宏“small”。这也在另一个SO问题中讨论过。
一种解决方法是在#include <windows.h>之后添加#undef small

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接