gcc fails to compile the code below, while clang compiles ok. I have no control on the macro PORTB, as it is in a 3rd party library (avr).
Is it a gcc bug? How can I work around it in gcc? As a workaround is somehow possible to create a pre-processor macro which extracts the numerical value from PORTB?
Note this question is similar, but not identical to my previous question.
It is also different from this question, where the developer has the flexibility to change the rhs of the assignment, thus avoiding the reinterpret_cast.
#include <iostream>
#include <cstdint>
#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))
struct PortB {
static const uintptr_t port = reinterpret_cast<uintptr_t>(&PORTB);
};
int main() {
std::cout << PortB::port << "\n";
return 0;
}
It seems reinterpret_cast is not allowed during compilation. Thus the newer version of the compiler simply is more conforming to the language. reinterpret_cast will not be allowed where a constexpr is required.
But maybe these workaround may help (compiles with g++ 9.2):
#include <iostream>
#include <cstdint>
#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))
struct PortB {
static uintptr_t port;
};
uintptr_t PortB::port = reinterpret_cast<uintptr_t>(&PORTB);
const uintptr_t freePort = reinterpret_cast<uintptr_t>(&PORTB);
#define macroPort reinterpret_cast<uintptr_t>(&PORTB)
int main() {
std::cout << PortB::port << "\n";
std::cout << freePort << "\n";
std::cout << macroPort << "\n";
return 0;
}
Related
The following code is rejected by both clang and gcc but accepted by msvc:
#include <iostream>
int main()
{
std::cout << unsigned long long(10);
}
The error is
error: expected primary-expression before 'unsigned'
godbolt
This should compile, right?
No, what you have shown should NOT compile. See Explicit type conversions on cppreference.com for details.
In a function-style cast, spaces are not allowed in the type name. For such types, you would need to use a C-style or C++-style cast instead, eg:
std::cout << ((unsigned long long)10);
or
std::cout << static_cast<unsigned long long>(10);
Otherwise, use a type alias instead, eg:
using ull = unsigned long long; // C++11 and later
or
typedef unsigned long long ull; // pre-C++11
std::cout << ull(10);
Note, the <cstdint> header may have a uint64_t type you can use, eg:
#include <cstdint>
std::cout << uint64_t(10);
or
std::cout << ((uint64_t)10);
or
std::cout << static_cast<uint64_t>(10);
That being said, for integer literals, you can alternatively use the ULL suffix (C++11 and later), eg:
std::cout << 10ULL;
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.
This question already has an answer here:
undefined behaviour somewhere in boost::spirit::qi::phrase_parse
(1 answer)
Closed 7 years ago.
I have a little grammar that I want to use for a work project. A minimum executable example is:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#pragma GCC diagnostic pop // pops
#include <iostream>
int main()
{
typedef unsigned long long ull;
std::string curline = "1;2;;3,4;5";
std::cout << "parsing: " << curline << "\n";
namespace qi = boost::spirit::qi;
auto ids = -qi::ulong_long % ','; // '-' allows for empty vecs.
auto match_type_res = ids % ';' ;
std::vector<std::vector<ull> > r;
qi::parse(curline.begin(), curline.end(), match_type_res, r);
std::cout << "got: ";
for (auto v: r){
for (auto i : v)
std::cout << i << ",";
std::cout << ";";
}
std::cout <<"\n";
}
On my personal machine this produces the correct output:
parsing: 1;2;;3,4;5
got: 1,;2,;;3,4,;5,;
But at work it produces:
parsing: 1;2;;3,4;5
got: 1,;2,;;3,
In other words, it fails to parse the vector of long integers as soon as there's more than one element in it.
Now, I have identified that the work system is using boost 1.56, while my private computer is using 1.57. Is this the cause?
Knowning we have some real spirit experts here on stack overflow, I was hoping someone might know where this issue is coming from, or can at least narrow down the number of things I need to check.
If the boost version is the problem, I can probably convince the company to upgrade, but a workaround would be welcome in any case.
You're invoking Undefined Behaviour in your code.
Specifically where you use auto to store a parser expression. The Expression Template contains references to temporaries that become dangling at the end of the containing full-expression¹.
UB implies that anything can happen. Both compilers are right! And the best part is, you will probably see varying behaviour depending on the compiler flags used.
Fix it either by using:
qi::copy (or boost::proto::deep_copy before v.1.55 IIRC)
use BOOST_SPIRIT_AUTO instead of BOOST_AUTO (mostly helpful iff you also support C++03)
use qi::rule<> and qi::grammar<> (the non-terminals) to type-erase and the expressions. This has performance impact too, but also gives more features like
recursive rules
locals and inherited attributes
declared skippers (handy because rules can be implicitly lexeme[] (see here)
better code organization.
Note also that Spirit X3 promises to drop there restrictions on the use with auto. It's basically a whole lot more lightweight due to the use of c++14 features. Keep in mind that it's not stable yet.
Showing that GCC with -O2 shows undefined results; Live On Coliru
The fixed version:
Live On Coliru
//#pragma GCC diagnostic push
//#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
//#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
//#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
//#pragma GCC diagnostic pop // pops
#include <iostream>
int main() {
typedef unsigned long long ull;
std::string const curline = "1;2;;3,4;5";
std::cout << "parsing: '" << curline << "'\n";
namespace qi = boost::spirit::qi;
#if 0 // THIS IS UNDEFINED BEHAVIOUR:
auto ids = -qi::ulong_long % ','; // '-' allows for empty vecs.
auto grammar = ids % ';';
#else // THIS IS CORRECT:
auto ids = qi::copy(-qi::ulong_long % ','); // '-' allows for empty vecs.
auto grammar = qi::copy(ids % ';');
#endif
std::vector<std::vector<ull> > r;
qi::parse(curline.begin(), curline.end(), grammar, r);
std::cout << "got: ";
for (auto v: r){
for (auto i : v)
std::cout << i << ",";
std::cout << ";";
}
std::cout <<"\n";
}
Printing (also with GCC -O2!):
parsing: '1;2;;3,4;5'
got: 1,;2,;;3,4,;5,;
¹ (that's basically "at the next semicolon" here; but in standardese)
I have some trouble using decltype for member function pointers:
#include <iostream>
#include <type_traits>
struct A
{
void func1() {}
typedef decltype(&A::func1) type;
};
int wmain(int argc, wchar_t* argv[])
{
typedef decltype(&A::func1) type;
//Case 1
std::wcout
<< std::boolalpha
<< std::is_member_function_pointer<type>::value
<< std::endl;
//Case 2
std::wcout
<< std::boolalpha
<< std::is_member_function_pointer<A::type>::value
<< std::endl;
system("pause");
return 0;
}
Case 1 prints true as expected, but Case 2 prints false.
Is decltype stripping away the "member" property of a type? If so, why?
Also, is there a way to prevent this behavior? I need to get the type of a member function regardless of where I use decltype.
Please help.
EDIT:
Reported to Microsoft
For the sake of formality (having an answer to the question), this appears to be a bug in VC2010's compiler. File a bug report so that Microsoft can fix it in the next version.
I'm currently trying to debug a piece of simple code and wish to see how a specific variable type changes during the program.
I'm using the typeinfo header file so I can utilise typeid.name(). I'm aware that typeid.name() is compiler specific thus the output might not be particularly helpful or standard.
I'm using GCC but I cannot find a list of the potential output despite searching, assuming a list of typeid output symbols exist. I don't want to do any sort of casting based on the output or manipulate any kind of data, just follow its type.
#include <iostream>
#include <typeinfo>
int main()
{
int a = 10;
cout << typeid(int).name() << endl;
}
Is there a symbol list anywhere?
I don't know if such a list exists, but you can make a small program to print them out:
#include <iostream>
#include <typeinfo>
#define PRINT_NAME(x) std::cout << #x << " - " << typeid(x).name() << '\n'
int main()
{
PRINT_NAME(char);
PRINT_NAME(signed char);
PRINT_NAME(unsigned char);
PRINT_NAME(short);
PRINT_NAME(unsigned short);
PRINT_NAME(int);
PRINT_NAME(unsigned int);
PRINT_NAME(long);
PRINT_NAME(unsigned long);
PRINT_NAME(float);
PRINT_NAME(double);
PRINT_NAME(long double);
PRINT_NAME(char*);
PRINT_NAME(const char*);
//...
}