“未声明的标识符”错误是什么,我该如何解决?

69

什么是未声明标识符错误?常见原因是什么,如何解决?

示例错误文本:

  • 对于Visual Studio编译器:error C2065: 'cout' : undeclared identifier
  • 对于GCC编译器:'cout' undeclared (first use in this function)

2
一个非常常见的情况是包含<iostream>并尝试使用std::string,而没有包含<string>。可能值得一提。 - πάντα ῥεῖ
13个回答

103

这种错误通常是由于忘记包含包含函数声明的头文件引起的,例如,该程序将会出现“未声明的标识符”错误:

缺少头文件

int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}

要修复它,我们必须包含头文件:
#include <iostream>
int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}

如果您编写了头文件并正确包含它,但头文件可能包含错误的包含保护
要了解更多信息,请参见http://msdn.microsoft.com/en-us/library/aa229215(v=vs.60).aspx

变量拼写错误

另一个初学者常犯的错误是拼写变量错误。
int main() {
    int aComplicatedName;
    AComplicatedName = 1;  /* mind the uppercase A */
    return 0;
}

作用域不正确

例如,这段代码会报错,因为你需要使用std::string

#include <string>

int main() {
    std::string s1 = "Hello"; // Correct.
    string s2 = "world"; // WRONG - would give error.
}

使用前未声明
void f() { g(); }
void g() { }

g在第一次使用之前未被声明。要修复它,请将g的定义移动到f之前:

void g() { }
void f() { g(); }

或者在 f 之前添加 g 的声明:

void g(); // declaration
void f() { g(); }
void g() { } // definition

stdafx.h 不在顶部(仅限于VS)

这是仅限于 Visual Studio 的问题。在 VS 中,您需要在任何代码之前添加 #include "stdafx.h"。它之前的代码将被编译器忽略,所以如果您有以下代码:

#include <iostream>
#include "stdafx.h"

"

需要将#include <iostream>移至下方,否则会被忽略。

"
#include "stdafx.h"
#include <iostream>

随意编辑此答案。


人们不应该编辑他人的答案,只需纠正错误或使其更好...但是,如果答案包含其他内容,可以自由添加,并提到这部分来自xxx。 - Robert
1
我刚刚浪费了几个小时查看一个类似的问题,而在我的情况下,问题出在头文件保护不正确。 - Jad
1
导致此错误的另一个棘手情况是:https://dev59.com/3Ww15IYBdhLWcg3wd7lj#6592617 - ymoreau
2
另一个需要检查的是交叉引用。 - enkara

21
考虑一下对话中的类似情况。想象一下,你的朋友对你说:“Bob要来我们家吃饭”,而你不知道谁是Bob。你会感到困惑,对吧?你的朋友应该说:“我有一个叫Bob的工作同事。Bob要来我们家吃饭。”现在Bob已经被解释清楚了,你知道你的朋友在谈论谁了。
当您尝试使用某个标识符(函数、变量、类等的名称)但编译器没有看到它的声明时,编译器会发出“未声明的标识符”错误。也就是说,编译器不知道你在引用什么,因为它以前没有见过它。
如果在C或C++中遇到这样的错误,意味着您没有告诉编译器您正在尝试使用的内容。声明通常在头文件中找到,所以很可能意味着您没有包含适当的头文件。当然,可能只是您完全忘记声明实体了。
一些编译器根据上下文给出更具体的错误。例如,在clang中尝试编译X x;,其中类型X尚未声明,将告诉您“未知类型名称X”。这更有用,因为您知道它正在尝试解释X为类型。但是,如果您有int x = y;,其中y尚未声明,则会告诉您“使用未声明的标识符y”,因为对于y可能代表的确切内容存在某种模棱两可的情况。

7

在C和C++中,所有变量名和函数名都必须在使用前进行声明。如果你试图使用一个未声明的变量或函数名称,你将会收到一个"未声明的标识符"错误。

不过,在C语言(仅限于C语言)中,函数是一种特殊情况,你不必先声明它们。C编译器会假定调用中函数已经存在,并且参数的数量和类型与调用相同。如果实际的函数定义与此不匹配,则会出现另一个错误。这种函数的特殊情况在C++中不存在。

为了解决这些错误,你需要确保在使用之前已经声明了变量和函数。对于printf,你需要包含头文件<stdio.h>(或C++中的<cstdio>)。

对于标准函数,我建议你查阅例如这个参考网站,并搜索你想要使用的函数。每个函数的文档都会告诉你需要哪个头文件。


6
我曾经遇到过一个与命名空间有关的自定义类问题。我试图在没有使用命名空间的情况下使用该类,导致编译器错误 "标识符"MyClass"未定义"。需要将命名空间添加到类的调用中。
using namespace <MyNamespace>

或者使用类似以下的方式
MyNamespace::MyClass myClass;

解决了问题。

3

这些错误信息

1.For the Visual Studio compiler: error C2065: 'printf' : undeclared identifier
2.For the GCC compiler: `printf' undeclared (first use in this function)

这意味着你在程序中使用了名称为“printf”的函数,但编译器并不知道该函数的声明及其含义。
任何在程序中使用的名称都必须在使用之前被声明。编译器需要知道名称所代表的含义。
在这种情况下,编译器没有看到名称为“printf”的函数声明。我们知道(但编译器不知道),它是标准C函数的名称,在C语言中声明在头文件<stdio.h>中,在C++语言中声明在头文件<cstdio>中,并位于标准(std ::)和全局(::)命名空间中(不一定)。因此,在使用此函数之前,我们必须通过包含相应的头文件向编译器提供其名称声明。
例如: C语言:
#include <stdio.h>

int main( void )
{
   printf( "Hello World\n" );
}

C++:

#include <cstdio>

int main()
{
   std::printf( "Hello World\n" );
   // or printf( "Hello World\n" );
   // or ::printf( "Hello World\n" );
}

有时候出现这种错误的原因可能只是简单的打错了字。例如,假设你定义了一个函数PrintHello
void PrintHello()
{
    std::printf( "Hello World\n" );
}

但是在主程序中,你犯了一个错别字,你打成了小写字母'p'的printHello,而不是PrintHello

#include <cstdio>

void PrintHello()
{
    std::printf( "Hello World\n" );
}

int main()
{
   printHello();
}

在此情况下,编译器会发出错误,因为它没有看到名称为printHello的声明。 PrintHelloprintHello 是两个不同的名称,其中一个被声明了,另一个在main函数体内被使用但未被声明。

在C++中,没有 std:: 的版本不能保证能够正常工作。 - M.M

3

当 Visual Studio 项目中的自动格式化程序排序后,预编译头文件不再是第一个 include 时,我遇到了这种情况。

换句话说,如果您有以下任何一种情况:

#include "pch.h"

或者

#include <stdio.h>

或者

#include <iostream>
#include "stdafx.h"

把它放在文件的开头。

如果您的clang格式化器正在自动排序文件,请尝试在预编译头之后换行。如果设置为IBS_Preserve,它将单独对每个#include块进行排序。

#include "pch.h"  // must be first

#include "bar.h"  // next block
#include "baz.h"
#include "foo.h"

更多信息请参见编译器错误 C2065


如果您在Visual Studio中尝试创建动态链接库项目,则必须将#include "pch.h"放在第一行。否则,将报告C2065错误。 - Zhen Yang

2

C++标识符是用于标识变量、函数、类、模块或任何其他用户定义的项目的名称。在C++中,所有名称都必须在使用之前声明。如果您尝试使用未声明的标识符名称,则会收到“未声明的标识符”编译错误。

根据文档printf()的声明位于cstdio中,即在使用该函数之前必须先包含它。


1

1

还有一种情况可能会出现这个问题,

if(a==b)
double c;
getValue(c);

这里,在条件语句中声明了一个值,然后在它之外使用。


0
大多数情况下,如果你非常确定已经导入了相关库,Visual Studio 将会通过 IntelliSense 来为你提供指导。
以下是对我有用的方法:
确保 #include "stdafx.h" 被首先声明,也就是在所有的包含项之前。

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