This question already has answers here:
Why is the address of this volatile variable always at 1?
(3 answers)
Closed 3 years ago.
In our code we use pointers to structures to deduct addresses of hardware registers to keep the code readable.
For example:
#include <cstdint>
#include <iostream>
struct reg {
uint32_t t;
uint32_t x;
uint32_t value;
};
int main(void)
{
struct reg *r = reinterpret_cast<struct reg *>(0x800000);
std::cerr << &r->value << "\n";
std::cerr << &r->t << "\n";
std::cerr << &r->x << "\n";
return 0;
}
The hardware-base-address is 0x800000 and using writeReg(&t->x, 123); will make it write to 0x800004.
By accident a volatile-keyword was wrongly placed in the structure-definition:
struct reg {
volatile uint32_t t;
volatile uint32_t x;
volatile uint32_t value;
};
What happened now is that all fields have the offset 1 using the &r->field-syntax.
Using g++ (Debian 9.2.1-4) 9.2.1 20190821 here.
Rewriting the test in C using printf and a C-style-cast gives again the correct offset even with volatile.
I'm unable to unable to understand why the volatile-keyword seems to break pointer-arithmetic? Why is that so? What is happening?
There is no overload of operator<< for printing pointers to volatile.
The best suitable overload your compiler finds is the one for printing bool, so your pointers get converted to bool.
Try:
std::cerr << (void *)&r->value << "\n";
Related
This question already has answers here:
uint8_t can't be printed with cout
(8 answers)
Closed 4 months ago.
#include<iostream>
#include<string>
class Person_t{
private:
uint8_t age;
public:
void introduce_myself(){
std::cout << "I am " << age << " yo" << std::endl;
}
Person_t()
: age{99}
{ };
};
int main(){
Person_t person1{};
person1.introduce_myself();
}
When the shown code is executed, the integer from the initializer list gets converted to a c. I have no explaination why, could someone please explain this to me?
<< age
age is a uint8_t, which is an alias for an underlying native type of a unsigned char. Your C++ library implements std::ostream's << overload for an unsigned char as a formatting operation for a single, lonely, character.
Simply cast it to an int.
<< static_cast<int>(age)
After compilation, what does the reference become, an address, or a constant pointer?
I know the difference between pointers and references, but I want to know the difference between the underlying implementations.
int main()
{
int a = 1;
int &b = a;
int *ptr = &a;
cout << b << " " << *ptr << endl; // 1 1
cout << "&b: " << &b << endl; // 0x61fe0c
cout << "ptr: " << ptr << endl; // 0x61fe0c
return 0;
}
The pedantic answer is: Whatever the compiler feels like, all that matters is that it works as specified by the language's semantics.
To get the actual answer, you have to look at resulting assembly, or make heavy usage of Undefined Behavior. At that point, it becomes a compiler-specific question, not a "C++ in general" question
In practice, references that need to be stored essentially become pointers, while local references tend to get compiled out of existence. The later is generally the case because the guarantee that references never get reassigned means that if you can see it getting assigned, then you know full well what it refers to. However, you should not be relying on this for correctness purposes.
For the sake of completeness
It is possible to get some insight into what the compiler is doing from within valid code by memcpying the contents of a struct containing a reference into a char buffer:
#include <iostream>
#include <array>
#include <cstring>
struct X {
int& ref;
};
int main() {
constexpr std::size_t x_size = sizeof(X);
int val = 12;
X val_ref = {val};
std::array<unsigned char, x_size> raw ;
std::memcpy(&raw, &val_ref, x_size);
std::cout << &val << std::endl;
std::cout << "0x";
for(const unsigned char c : raw) {
std::cout << std::hex << (int)c;
}
std::cout << std::endl ;
}
When I ran this on my compiler, I got the (endian flipped) address of val stored within the struct.
it heavily depend on compiler maybe compiler decide to optimize the code therefore it will make it value or ..., but as far i know references will compiler like pointer i mean if you see their result assembly they are compiled like pointer.
This question already has answers here:
Accessing inactive union member and undefined behavior?
(5 answers)
Closed 2 years ago.
For the following code
#include <iostream>
using namespace std;
union type
{
int a;
char b ;
};
int main()
{
type first;
first.b = 'a';
cout << first.a << " " << first.b << endl;
}
the output is -858993567 a (MSVC) or 4201057 a(g++ MINGW).
but for
#include <iostream>
using namespace std;
union type
{
int a;
char b ;
};
int main()
{
type first;
first.a = 0;
first.b = 'a';
cout << first.a << " " << first.b << endl;
}
the output is 97 a
And these values are fixed under every circumstances (tried rebooting and creating new workspace/file, hence not garbage values).
So, why did the initialization (in the second case) made a difference?
I have tried it both on visual studio (using MSVC) and visual studio code (using g++).
Update 1
I checked on online IDE which probably use Linux g++, and they give the exact expected answer i.e., 97 a, in both the cases.
If you specify first.a in first code sample - you will get fixed, stable value.
You have union with 4 bytes size and initialize only one byte of them.
Union is like type who can holds any type but this types musts be writed in definition of union, like this:
union Example {
char a;
std::int32_t b;
};
Example ex; /// Create object of union
ex.a = 'c'; /// At this moment a member is valid and b is invalid
std::cout << ex.b; /// This cause undefined behavior
Be aware, size of union object is size of type who need most bytes. In this case size is same as size of b property.
My program won't allow me to output these values because the "type name is not allowed" (highlighted in asterisks). What does that mean? What's wrong? I'm trying to parse this MIDI file, and it seems I need to use these data types, as the program was outputting the incorrect values (only MThd was outputting correctly, the rest were random hex values). What can I do to fix this? I'm new to coding, so sorry if this is a stupid question.
#include <iostream>
#include <fstream>
#include <stdint.h>
typedef struct MIDI_CHUNK_HEADER {
char MThd[4];
typedef uint32_t ChunckSize[4];
typedef uint16_t Format[2];
typedef uint16_t Track[2];
typedef uint16_t TimeDivision[2];
} MIDI_CHUNK_HEADER;
int main()
{
std::ifstream In_File("C:\\Users\\micah\\Documents\\Twinkle.mid", std::ios::binary | std::ios::in);
if (!In_File)
{
std::cerr << "Problem opening file!";
return 1;
}
MIDI_CHUNK_HEADER midi_chunk_header;
In_File.read((char*)&midi_chunk_header, sizeof(MIDI_CHUNK_HEADER));
std::cout << "File type is: "<< midi_chunk_header.**MThd** << std::endl;
std::cout << "Bytes to follow: " << midi_chunk_header.**ChunckSize** << std::endl;
std::cout << "MIDI Format: " << midi_chunk_header.**Format** << std::endl;
std::cout << "MIDI Track: " << midi_chunk_header.**Track** << std::endl;
std::cout << "MIDI Time Division: " << midi_chunk_header.**TimeDivision** << std::endl;
}
typedef declares an alias for a type name. It does not declare a variable. You cannot use a type name in an expression as if it was a variable name.
If you intended to declare class members, then drop the typedef. Also don't use typedef struct in C++. It has use in C, but is redundant in C++. A class can be defined directly without typedef:
struct MIDI_CHUNK_HEADER {
char MThd[4];
uint32_t ChunckSize[4];
uint16_t Format[2];
uint16_t Track[2];
uint16_t TimeDivision[2];
};
Furthermore you cannot output arrays directly with <<. It will print the address of the first array element instead, except for the case of char arrays (which will be interpreted as C style null-terminated strings). You need to loop over the individual elements and output each individually.
(Without looking at the MIDI chunk header format specification:) It seems that you don't actually want arrays at all. If you want e.g. ChunckSize to represent 4 bytes, then you want only one uint32_t (which is 32bits equaling 4 bytes already by itself), not four of them:
struct MIDI_CHUNK_HEADER {
char MThd[4];
uint32_t ChunckSize;
uint16_t Format;
uint16_t Track;
uint16_t TimeDivision;
};
Please learn the language from a good book. It would explain how everything works in a structured way and you wouldn't make mistakes such as using typedef here. Learning C++ in an unstructured way will not get you far. C++ is too unforgiving to mistakes.
I perform some calculations, based on the result, I would like to either use a short int or int for some type of data for the remaining program. Can (/How can) this be done sensibly in C or C++? I don't really care about the amount of memory used (i.e., 2 or 4 bytes), my primary aim is to access generic arrays as if they contained data of this type. I would like to avoid code such as the following:
char s[128];
if (result of preliminary calculations was A)
*((int*) s) = 50;
else
*((short int*) s) = 50;
to set the first 4 or 2 bytes of s. A conditional global typedef would be ideal:
if (result of preliminary calculations was A)
typedef int mytype;
else
typedef short int mytype;
I am not that familiar with C++ class templates (yet). Do they apply to my problem? Would I have to change the declarations throughout my program (to myclass< > and myclass< >*)?
Many thanks!
Frank
Edit: The values may not always be aligned. I.e, a int can start at position 21. Thanks for the answers.
For plain C, you could do this using function pointers:
static union { s_int[32]; s_short[64]; s_char[128]; } s;
static void set_s_int(int i, int n)
{
s.s_int[i] = n;
}
static int get_s_int(int i)
{
return s.s_int[i];
}
static void set_s_short(int i, int n)
{
s.s_short[i] = n;
}
static int get_s_short(int i)
{
return s.s_short[i];
}
static void (*set_s)(int, int);
static int (*get_s)(int);
Set them once based on the preliminary calculations:
if (result of preliminary calculations was A)
{
set_s = set_s_int;
get_s = get_s_int;
}
else
{
set_s = set_s_short;
get_s = get_s_short;
}
Then just use the function pointers in the rest of the program:
set_s(0, 50); /* Set entry 0 in array to 50 */
Your file writing function can directly reference s or s.s_char depending on how it works.
In C and C++, all type information is defined at Compile-time. So no, you cannot do this.
If the result of the preliminary calculations can be found at compile time, then this can work. Here are some simple examples to show how this can work. To do more complicated examples, see http://en.wikipedia.org/wiki/Template_metaprogramming
using namespace std;
#include <iostream>
template<int x> struct OddOrEven { typedef typename OddOrEven<x-2>::t t; };
template<> struct OddOrEven<0> { typedef short t; };
template<> struct OddOrEven<1> { typedef int t; };
template<bool makeMeAnInt> struct X { typedef short t; };
template<> struct X<true> { typedef int t; };
int main(void) {
cout << sizeof(X<false>::t) << endl;
cout << sizeof(X<true>::t) << endl;
cout << sizeof(OddOrEven<0>::t) << endl;
cout << sizeof(OddOrEven<1>::t) << endl;
cout << sizeof(OddOrEven<2>::t) << endl;
cout << sizeof(OddOrEven<3>::t) << endl;
cout << sizeof(OddOrEven<4>::t) << endl;
cout << sizeof(OddOrEven<5>::t) << endl;
}
I think above is standard C++, but if not I can tell you this work on g++ (Debian 4.3.2-1.1) 4.3.2
I think your main problem is how you plan to read the data from s later on if you don't know what type to read.
If you have that part covered, you can use a union:
union myintegers
{
int ints[32];
short shorts[64];
};
Now simply use the type you want.
myintegers s;
if (result of preliminary calculations was A)
s.ints[0] = 50;
else
s.shorts[0] = 50;
As a step further, you could wrap it all in a class which is constructed with result of preliminary calculations was A and overrides the operators * and [] to store in one or the other.
But are you sure you want any of that?
In current C++ standard (C++03), you can't.
In fact you can use some advanced metaprogramming tricks but it will not help most of the time.
In the next standard (C++0x, certainly C++11 in the end), you will be able to use the keyword decltype to get the type of an expression. If you're using VC10 (VS2010) or GCC 4.4 or more recent, then you already have the feature available.
You could abuse templates for this purpose. Any code that's subject to the decision would have to be templated based on the int type. One branch would instantiate the int version, the other would instantiate the short int version. This is probably a bad idea*.
Edit
*Well, it's only a bad idea to apply this to your overall architecture. If you have a particular data type that encapsulates the varied behavior, a template should work just fine.
Here's a variation on Aaron McDaid's answer to illustrate it's use with conditions:
#include <iostream>
#include <string>
using namespace std;
template<int x> struct OddOrEven { typedef typename OddOrEven<x-2>::t t; };
template<> struct OddOrEven<0> { typedef short t; };
template<> struct OddOrEven<1> { typedef int t; };
int main() {
cout << "int or short? ";
string which;
cin >> which;
if (which.compare("int") == 0)
cout << sizeof(OddOrEven<1>::t) << endl;
else if (which.compare("short") == 0)
cout << sizeof(OddOrEven<0>::t) << endl;
else
cout << "Please answer with either int or short next time." << endl;
return 0;
}
This is a code snippet from a project I had a while back.
void* m_pdata;
if (e_data_type == eU8C1){
pimage_data = new unsigned char[size_x * size_y];
}
if (e_data_type == eU16C1){
pimage_data = new unsigned short[size_x * size_y];
}
I hope it can help you
Since your stated goal is to store information efficiently on disk, you should learn to stop writing memory images of C/C++ data structures to disk directly and instead serialize your data. Then you can use any of a number of forms of variable-length coding ("vlc") to get the effect you want. The simplest is a coding with 7 bits per byte where the 8th bit is a continuation flag indicating that the value is continued in the next byte. So 259 would be stored as (binary, with continuation bit marked by spacing and byte boundaries marked by ;):
1 0000010 ; 0 0000011
Alternatively you could use the head nibble to signal the number of bytes that will follow, or use a scheme similar to UTF-8 with slightly more overhead but stricter resynchronization guarantees. There are also vlcs with are designed to be parsable and easily resynchronized when reading either forward or in reverse.