Wednesday, January 5, 2022

[SOLVED] source is compiled without proper #include

Issue

I have a very simple c++ source like this:

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

I am using g++ to compile like this :

g++ ./test.cpp

but it successfully compiles despite the fact that time() function is defined in ctime and it is not included with #include

my professor at university runs the code with visual studio (vc++) but he is unable to run the code without including ctime

Am I missing something here ?

by the way my g++ version is :

g++ (Ubuntu 11.2.0-7ubuntu2) 11.2.0


Solution

First of all, on my platform, it didn't compile successfully when I removed #include <iostream> I am using WSL2 ubuntu 20.04, compiler i used g++ and clang++.
Whichever compiler it is, it gives the error:

>>> 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.

I think you can use the compile option -E to prompt the compiler to do only preprocessing and to see the preprocessed file.
like this:
g++ t.cpp -E -o pre_proccessed.cpp Determine whether the compiler did what you suspect it did during the compilation process, "automatically include the file"

But, when I add #include <iostream> It did success.
So, I did this:

>>>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;

This explains why its compilation succeeded, because the iostream file included in this platform has the definition of this function in it.
In addition, look at this problam

In fact, stl are allowed to include each other.
But even though it is defined in this header file, you cannot rely on it, some versions of the iostream implementation do not include this.

What you should do is to actively include the cstdlib file when using srand, don't worry about the multiple inclusion problem, std,stl itself can handle multiple inclusion very well, and modern compilers can also handle this problem very well.



Answered By - MuxAte