So, I have the following code, and it builds and runs perfectly, tried various values and all is well. You'll notice I use log10 function and I do not include cmath or math.h. Why does it still build and run fine? Are those libraries really needed? Why/Why not? Does it have anything to do with me using visual studio? Like, would it not compile if say I was using a different IDE or command prompt to compile it?
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Classify solutions as acidic or nonacidic" << endl<< endl;
//declaring double molar concentration
double mc = 1;
//using while and if statements to calculate pH in fixed notaion and acidic or nonacidic
while (mc != 0)
{
cout << "Please enter a molar concentration (or enter 0 to exit): ";
cin >> mc;
if (mc != 0)
{
cout << "Molar Conentration = " << scientific << mc << endl; //scientific notation
double pH = -log10(mc);
cout << "pH = " << fixed << setprecision(6) << pH << endl; //6 deciumals
if (pH > 7)
{
cout << "Nonacidic" << endl << endl;
}
else if (pH < 7)
{
cout << "Acidic" << endl << endl;
}
else
cout << "Neutral" << endl << endl;
}
}
//end program when inputing 0
cout << "End of Program" << endl;
return 0;
}
Cmath library is an essential part of the C++ programming language as it provides many operations and functions of mathematics when we use the programs to execute source codes.
The math module supplies mathematical functions on floating-point numbers, while the cmath module supplies equivalent functions on complex numbers.
The cmath header file contains definitions for C++ for computing common mathematical functions. Include the standard header into a C++ program to effectively include the standard header < math. h > within the std namespace.
The C++ <cmath> header file declares a set of functions to perform mathematical operations such as: sqrt() to calculate the square root, log() to find natural logarithm of a number etc.
The code:
i = i++ + ++i;
may also compile okay, but that doesn't make it a good idea :-)
It would be wise to include headers for library functions that you use. You don't lose any functionality by doing so but you do guarantee the functionality will work (misuse notwithstanding).
Detailed analysis follows.
Even if an implementation is relaxed about this, the standard mandates it. C++11 17.6.2.2 Headers /3
states:
A translation unit shall include a header only outside of any external declaration or definition, and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
The gcc
compiler, for example, will grumble bitterly about your code:
xyzzy.cpp: In function 'int main()':
xyzzy.cpp:22:34: error: 'log10' was not declared in this scope
double pH = -log10(mc);
^
As to why VC++ seemingly violates this rule, it has to do with the fact that header files are allowed to include other header files.
If you compile your code to produce pre-processor output (with /P
), you'll find a line buried deep within it thus (at least in VS2013):
#line 1 "c:\\blah\\blah\\vc\\include\\cmath"
And a bit of analysis turns up the following hierarchy of includes:
iostream
istream
ostream
ios
xlocnum
cmath
(<xlocnum>
, one of the internal headers used by <locale>
, appears to need ldexp()
from the <cmath>
library, though there may be others as well).
That's further evidenced by the fact that VC++ does complain about the following code:
//#include <iostream>
using namespace std;
int main() {
double oneHundred = 100;
int two = log10 (oneHundred);
return two;
}
with:
error C3861: 'log10': identifier not found
but that error disappears the instant you uncomment the iostream
inclusion line.
However, as previously stated, that is not behaviour you should rely on. If you are going to use a library function (or macro/template/whatever), it's up to you to include the correct header.
Otherwise your program compiling correctly is simply an accident.
As you've noticed, the code snippet you provided works in Visual Studio but not with other compilers. This is because of how the standard library is implemented for each compiler.
It turns out that when you include Visual Studio's implementation of <iostream>
, you end up including a bunch of other headers indirectly, and one of these headers is <cmath>
.
To see the exact chain, navigate to the standard library include directory. For me (I use Visual Studio 2013 Community Edition) this is located at
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include
#include <istream>
#include <ostream>
#include <ios>
#include <xlocnum>
#include <cmath>
Guess what? You included cmath when you included iostream... so your code is good to go, on Visual Studio at least. But, don't rely on implementation details or your code will break if you try to migrate it to another platform/toolchain.
For example, trying to compile the provided snippet using g++ on Cygwin results in the following error:
temp.cpp: In function ‘int main()’:
temp.cpp:22:34: error: ‘log10’ was not declared in this scope
double pH = -log10(mc);
This must mean g++'s implementation of <iostream>
doesn't depend on <cmath>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With