【问题标题】:source is compiled without proper #include源代码编译时没有正确的#include
【发布时间】:2022-01-17 12:19:50
【问题描述】:

我有一个非常简单的 c++ 源代码,如下所示:

#include <iostream>
int main() {
    srand(time(NULL));
}

我正在使用 g++ 像这样编译:

g++ ./test.cpp

但尽管time() 函数在ctime 中定义并且它不包含在#include 中,但它仍成功编译

我的大学教授使用 Visual Studio (vc++) 运行代码,但如果不包含 ctime,他将无法运行代码

我在这里错过了什么吗?

顺便说一句,我的 g++ 版本是:

g++ (Ubuntu 11.2.0-7ubuntu2) 11.2.0

【问题讨论】:

  • 标准头文件允许包含其他标准头文件。不要依赖这个。始终包含您需要的标题
  • 关于 C++ random 的旁注,请查看 头文件。 (srand 是 IMO 剩下的一点“C”)
  • @RemyLebeau yes.final 结论正是你所说的。但它可能会误导一个新的 c++ 程序员!
  • @PepijnKramer 是的,你是对的。实际上这个 c++ 代码是从 c 对应的翻译过来的!

标签: c++ gcc compilation time.h ctime


【解决方案1】:

首先,在我的平台上,当我删除#include &lt;iostream&gt;时它没有编译成功 我使用的是 WSL2 ubuntu 20.04,编译器我使用了 g++ 和 clang++。
无论是哪个编译器,它都会给出错误:

>>> g++ t.cpp
t.cpp: In function ‘int main()’:
t.cpp:2:16: error: ‘NULL’ was not declared in this scope
    2 |     srand(time(NULL));
      |                ^~~~
t.cpp:1:1: note: ‘NULL’ is defined in header ‘<cstddef>’; did you forget to ‘#include <cstddef>’?
  +++ |+#include <cstddef>
    1 | int main() {
t.cpp:2:11: error: ‘time’ was not declared in this scope
    2 |     srand(time(NULL));
      |           ^~~~
t.cpp:2:5: error: ‘srand’ was not declared in this scope
    2 |     srand(time(NULL));
      |     ^~~~~
>>>clang t.cpp
t.cpp:2:16: error: use of undeclared identifier 'NULL'
    srand(time(NULL));
               ^
1 error generated.

我认为您可以使用编译选项 -E 来提示编译器只进行预处理并查看预处理后的文件。
像这样:
g++ t.cpp -E -o pre_proccessed.cpp 判断编译器在编译过程中是否做了你怀疑的事情,“自动包含文件”

但是,当我添加#include &lt;iostream&gt; 它确实成功了。
所以,我这样做了:

>>>g++ t.cpp -E  -o t_.cpp
>>>cat t_.cpp | grep srand
extern void srandom (unsigned int __seed) throw ();
extern int srandom_r (unsigned int __seed, struct random_data *__buf)
extern void srand (unsigned int __seed) throw ();
extern void srand48 (long int __seedval) throw ();
extern int srand48_r (long int __seedval, struct drand48_data *__buffer)
  using ::srand;

这就解释了为什么它编译成功了,因为这个平台包含的iostream文件里面有这个函数的定义。
另外看看这个problam

其实stl是允许互相包含的。
但是即使在这个头文件中定义了它,你也不能依赖它,一些版本的iostream实现不包含这个。

你应该做的是在使用srand时主动包含cstdlib文件,不用担心多重包含的问题,std,stl本身可以很好的处理多重包含,现代编译器也可以处理这个问题很好。

【讨论】:

  • 其实我现在检查了srand() 定义在stdlib.hNULL 定义在stddef.h。尽管这些也不包括在内,但我的代码编译!!!
  • @MohamadrezaNakhleh 查看答案更新。
  • @MohamadrezaNakhleh 使用cat 命令查看该文件中的内容并使用| grep srand 验证该文件中是否包含 srand。
  • 好吧,看来你是对的! ` extern void srandom (unsigned int __seed) noexcept (true); extern int srandom_r (unsigned int __seed, struct random_data *__buf) extern void srand (unsigned int __seed) noexcept (true); extern void srand48 (long int __seedval) noexcept (true); extern int srand48_r (long int __seedval, struct drand48_data *__buffer) 使用 ::srand; srand(时间(`现在我明白了。谢谢
【解决方案2】:

首先明确包含您需要的内容,
(感谢 darkblueflow 指出)
其次 #include 订单很重要,

信不信由你,他们可以影子宣言, 如果第一种情况不起作用,只需切换

#include <cstdlib>
#include <ctime>

// differs from

#include <ctime>
#include <cstdlib>

// in some aspects

最好的办法是明确包含标题 记住这一点 this 祝你好运

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 2011-08-21
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多