Avoiding compiler issues with abs() - c++

When using the double variant of the std::abs() function without the std with g++ 4.6.1, no warning or error is given.
#include <algorithm>
#include <cmath>
double foobar(double a)
{
return abs(a);
}
This version of g++ seems to be pulling in the double variant of abs() into the global namespace through one of the includes from algorithm. This looks like it is now allowed by the standard (see this question), but not required.
If I compile the above code using a compiler that does not pull the double variant of abs() into the global namespace (such as g++ 4.2), then the following error is reported:
warning: passing 'double' for argument 1 to 'int abs(int)'
How can I force g++ 4.6.1, and other compilers that pull functions into the global namespace, to give a warning so that I can prevent errors when used with other compilers?

The function you are using is actually the integer version of abs, and GCC does an implicit conversion to integer.
This can be verified by a simple test program:
#include <iostream>
#include <cmath>
int main()
{
double a = -5.4321;
    double b = std::abs(a);
double c = abs(a);
std::cout << "a = " << a << ", b = " << b << ", c = " << c << '\n';
}
Output is:
a = -5.4321, b = 5.4321, c = 5
To get a warning about this, use the -Wconversion flag to g++. Actually, the GCC documentation for that option explicitly mentions calling abs when the argument is a double. All warning options can be found here.

Be warned, you don't need to explicitly #include <cmath>, <iostream> does the damage as well (and maybe some other headers). Also, note that -Wall doesn't give you any warnings about it.
#include <iostream>
int main() {
std::cout << abs(.5) << std::endl;
std::cout << typeid(decltype(abs)).name() << std::endl;
}
Gives output
0
FiiE
On
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04)

Related

C++ did not generate warning

I had a simple typo in my code. I wanted to do const std::string a = b + "bar"; but instead accidentally had const std::string a = a + "bar"; To my surprise, this did not generate any warnings from GCC 9.3.0 even though I compiled with -std=c++17 -Wall. Moreover, I did not get a warning for an unused variable b. How can that be? What flags should I have passed to GCC to generate at least some warning to catch this problem?
#include <string>
#include <iomanip>
#include <iostream>
namespace {
const std::string b = "foo";
const std::string a = a + "bar";
}
int main()
{
std::cout << "a is " << std::quoted(a) << std::endl;
return 0;
}
The way you are using the variable a, it has an indeterminate value that is either a trap representation or a unspecified value. It can in some cases(implementation) cause undefined behavior.
GCC 11.1.0 does generate warning it seems as seen here
#include <string>
#include <iomanip>
#include <iostream>
int main()
{
int a = a + 1;//this generates warning in gcc 11.1.0
std::string p = p + "some string";//this also generate warning in gcc 11.1.0
return 0;
}
But GCC 9.3.0 only gives warning for int as seen here
On the other hand clang gives warning for both.

error: uint64_t was not declared in this scope when compiling C++ program

I am trying out a simple program to print the timestamp value of steady_clock as shown below:
#include <iostream>
#include <chrono>
using namespace std;
int main ()
{
cout << "Hello World! ";
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
cout<<"Value: " << now << endl;
return 0;
}
But whenever I am compiling like this g++ -o abc abc.cpp, I am always getting an error:
In file included from /usr/include/c++/4.6/chrono:35:0,
from abc.cpp:2:
/usr/include/c++/4.6/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
abc.cpp: In function âint main()â:
abc.cpp:7:3: error: âuint64_tâ was not declared in this scope
abc.cpp:7:12: error: expected â;â before ânowâ
abc.cpp:8:22: error: ânowâ was not declared in this scope
Is there anything wrong I am doing?
Obviously, I'm not following certain best practices, but just trying to get things working for you
#include <iostream>
#include <chrono>
#include <cstdint> // include this header for uint64_t
using namespace std;
int main ()
{
{
using namespace std::chrono; // make symbols under std::chrono visible inside this code block
cout << "Hello World! ";
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
cout<<"Value: " << now << endl;
}
return 0;
}
and then compile using C++11 enabled (c++0x in your case)
g++ -std=c++0x -o abc abc.cpp
You should include stdint.h file.
If you really want to include, add "#define __STDC_LIMIT_MACROS"
Ref: https://stackoverflow.com/a/3233069/6728794

lowest() is not a member of std::numeric_limits

I am trying to compile the following code:
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<int>::lowest() << std::endl;
}
and I get the following error:
../main.cpp:5: error: 'lowest' is not a member of 'std::numeric_limits<int>'
cout << std::numeric_limits<int>::lowest() << std::endl;
^
I am using QT Creator 3.1.1 on Ubuntu 15.04, the compiler is set to GCC by default (/usr/bin/g++).
Anyone have an idea what could be the problem?
The lowest function was introduced in the C++11 standard, so you need to enable C++11 compatibility with the -std=c++11 flag (it's not enabled by default).

Why is there not any warning on a declaration without initialization in a for loop?

I tried to compile the following code using g++ (gcc version 4.8.2 (Debian 4.8.2-1)), with -Wall flag (adding the -Wextra flag does not change anything for me).
#include <iostream>
using namespace std ;
int main() {
int i ;
cout << i << endl ;
}
It gave this warning:
test.cpp: In function ‘int main()’:
test.cpp:7:13: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]
cout << i << endl ;
But the following code does not yield any warning:
#include <iostream>
using namespace std ;
int main() {
for(int i ; i < 10 ; i++) {
cout << i << endl ;
}
}
I did further tests.
The following yields the warning:
#include <iostream>
using namespace std ;
int main() {
int i ;
while(i<10) {
cout << i << endl ;
}
}
But the following does not:
#include <iostream>
using namespace std ;
int main() {
int i ;
while(i<10) {
cout << i << endl ;
i++ ;
}
}
In the above program, if I replace the while by an if, then I have a warning.
Is there some explanation to this? Why can the compiler recognize the problem in some cases and not in others, although they seem very close?
Thanks to Pradhan who gave this link, I understood the problem.
This link states the following:
GCC has the ability to warn the user about using the value of a uninitialized variable. Such value is undefined and it is never useful. It is not even useful as a random value, since it rarely is a random value. Unfortunately, detecting when the use of an uninitialized variable is equivalent, in the general case, to solving the halting problem. GCC tries to detect some instances by using the information gathered by optimisers and warns about them when the option -Wuninitialized is given in the command line. There are a number of perceived shortcomings in current implementation. First, it only works when optimisation is enabled through -O1, -O2 or -O3. Second, the set of false positives or negatives varies according to the optimisations enabled. This also causes high variability of the warnings reported when optimisations are added or modified between releases.
Indeed, when I add one of these flags, the compiler yields the warning.

linking <iostream.h> in linux using gcc

I'm trying to run my very first c++ program in linux (linux mint 8). I use either gcc or g++, both with the same problem: the compiler does not find the library I am trying to import.
I suspect something like I should either copy the iostream.h file (which I don't know where to look for) in the working folder, move my file to compile somewhere else or use an option of some sort.
Thanks for your suggestions.
Here's the gcc command, the c++ code, and the error message:
gcc -o addition listing2.5.c
.
#include <iostream.h>
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
cout << "Resultat : " << Addition(2, 4) << "\n";
return 0;
}
.
listing2.5.c:1:22: error: iostream.h: No such file or directory
listing2.5.c: In function ‘main’:
listing2.5.c:10: error: ‘cout’ undeclared (first use in this function)
listing2.5.c:10: error: (Each undeclared identifier is reported only once
listing2.5.c:10: error: for each function it appears in.)
Now the code compiles, but I cannot run it from the command line using the file name. addition: command not found Any suggestion?
cout is defined in the std:: namespace, you need to use std::cout instead of just cout.
You should also use #include <iostream> not the old iostream.h
use g++ to compile C++ programs, it'll link in the standard c++ library. gcc will not. gcc will also compile your code as C code if you give it a .c suffix. Give your files a .cpp suffix.
please use g++ not gcc to compile it
You need <iostream> not <iostream.h>.
They are also header files not libraries.
Other things to fix, cout should be std::cout and you should use std::endl instead of "\n".
You need <iostream>, <iostream.h> is non-standard too-old header. Try this:
#include <iostream>
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
using namespace std;
cout << "Resultat : " << Addition(2, 4) << "\n";
return 0;
}
If you don't want to use std alongside cout as below-
std::cout << "Hello World";
You can also define std at beginning of program by 'using namespace' keywords as-
#include <iostream >
using namespace std;
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
cout << "Result : " << Addition(2, 4) << "\n";
return 0;
}
Now you need not to write std,everytime you use I/O operations.