C++ did not generate warning - c++

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.

Related

Usage of reference that has not yet been initialized

Having the following small example, which is obvious not working, because the used reference has not yet been initialized when used.
#include <iostream>
using namespace std;
struct Test {
int MyCopy{myRef};
int& myRef{myNumber};
int myNumber{50};
};
int main()
{
Test myTest;
cout << myTest.MyCopy << endl;
return 0;
}
Why is the compiler not throwing any warning about the problem? Enabled all possible warning levels in g++ (-Wall -Weffc++ -Wextra). Can the compiler not recognise the problem?

C string as template non-type parameter works in gcc 6.3 but does not work in Visual Studio 2017 (19.16.27027.1 for x64)

The following code:
#include <iostream>
template<const char* Pattern> void f() {
std::cout << Pattern << "\n";
}
static constexpr const char hello[] = "Hello";
int main() {
f<hello>(); //Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27027.1 for x64
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// string-as-template-parameter.cpp
// string-as-template-parameter.cpp(10): fatal error C1001: An internal error has occurred in the compiler.
// (compiler file 'msc1.cpp', line 1518)
// To work around this problem, try simplifying or changing the program near the locations listed above.
// Please choose the Technical Support command on the Visual C++
return 0;
}
works when compiled by gcc (g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516) but results in C1001 when compiled by VS 2017.
As a workaround I use:
#include <iostream>
template<const char** Pattern> void f() {
std::cout << *Pattern << "\n";
}
static const char* hello = "Hello";
int main() {
f<&hello>();
return 0;
}
Does anybody have idea of more beautiful solution? May be initial code has an error which is skipped by gcc?
Does anybody have idea of more beautiful solution?
You can use a reference to std::string instead.
#include <iostream>
#include <string>
template<std::string & Pattern> void f() {
std::cout << Pattern << "\n";
}
static std::string hello = "Hello";
int main() {
f<hello>();
return 0;
}
This compiles with MSVC in Visual Studio.
This works because as per Cppreference, a named lvalue reference with linkage is allowed as a non-type parameter. (Note that hello is not local.)

How to print hex from uint32_t?

The code I have been working on requires that I print a variable of type uint32_t in hexadecimal, with a padding of 0s and minimum length 8. The code I have been using to do this so far is:
printf("%08lx\n",read_word(address));
Where read_word returns type uint32_t. I have used jx, llx, etc. formats to no avail, is there a correct format that can be used?
EDIT:
I have found the problem lies in what I am passing. The function read_word is returns a value from a uint32_t vector. It seems that this is the problem that is causing problems with out putting hex. Is this a passing by reference/value issue and what is the fix?
read_word function:
uint32_t memory::read_word (uint32_t address) {
if(address>(maxWord)){
return 0;
}
return mem[address];
}
mem deceleration:
std::vector<uint32_t> mem=decltype(mem)(1024,0);
To do this in C++ you need to abuse both the fill and the width manipulators:
#include <iostream>
#include <iomanip>
#include <cstdint>
int main()
{
uint32_t myInt = 123456;
std::cout << std::setfill('0') << std::setw(8) << std::hex << myInt << '\n';
}
Output
0001e240
For C it gets a little more obtuse. You use inttypes.h
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main()
{
uint32_t myInt = 123456;
printf("%08" PRIx32 "\n", myInt);
return 0;
}
Output
0001e240
Note that in C, the constants from inttypes.h are used with the language string-concatenation feature to form the required format specifier. You only provide the zero-fill and minimum length as a preamble.
%jx + typecast
I think this is correct:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t i = 0x123456;
printf("%08jx\n", (uintmax_t)i);
return 0;
}
compile and run:
gcc -Wall -Wextra -pedantic -std=c99 main.c
./a.out
Output:
00123456
Let me know if you can produce a failing test case.
Tested in Ubuntu 16.04, GCC 6.4.0.

Avoiding compiler issues with abs()

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)

Why do statements after return change the return value?

C++ returns invalid value in the following code:
#include <iostream>
#include <vector>
using namespace std;
int f(){
vector< int * > v[2];
return 1;
v[1].push_back(NULL);
}
int main(){
cout << f();
}
The output is:
205960
When I commnet line after return, it works fine:
#include <iostream>
#include <vector>
using namespace std;
int f(){
vector< int * > v[2];
return 1;
//v[1].push_back(NULL);
}
int main(){
cout << f();
}
The output is:
1
I am using code::blocks with mingw32-g++.exe compiler. The mingw version is: gcc version 4.4.1 (TDM-2 mingw32).
Your compiler has a bug. Fortunately, it is also obsolete. You should upgrade — G++ is up to version 4.6.2, which also implements much of C++11, which is very useful.
If you choose to stick with an older compiler, that is also a decision to accept its flaws.
Edit: If you are really stuck with 4.4 (for example due to a PHB), that series is still maintained. You can upgrade to GCC 4.4.6, released just this past April.