13 Replies - 916 Views - Last Post: 23 June 2019 - 11:41 AM Rate Topic: -----

#1 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

How to print struct bitfield in one go in C++ ?

Posted 22 June 2019 - 06:34 PM

I was able to do that in C, but I couldn't do it in C++!


Here are my codes:

1. In C, it works pretty well:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>


struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};


int main(){

printf("%d\n",sizeof(struct varNode));
struct varNode reg1;
reg1.s1 = 0x02;
reg1.s2 = 0x07;
reg1.s3 = 0x01;
printf("0x%.2X",reg1);


    return 0;
}



2. In C++, it's not working and gives me error that there's no match for << operator:

#include <iostream>
#include <string>
#include <fstream>
#include  <iomanip>
#include <boost/format.hpp>

using namespace std;


struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};


int main () {

cout << sizeof(varNode) << endl;

struct varNode reg1;

reg1.s1 = 0x02;
reg1.s2 = 0x07;
reg1.s3 = 0x01;


cout << "0x" << setfill('0') << setw(2) << hex << +reg1 << endl;
//cout << boost::format("0x%02x\n") % reg1; // also tried boost library format


  return 0;
}


This post has been edited by wolfrose: 23 June 2019 - 01:31 AM


Is This A Good Question/Topic? 1
  • +

Replies To: How to print struct bitfield in one go in C++ ?

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6969
  • View blog
  • Posts: 23,685
  • Joined: 05-May 12

Re: How to print struct bitfield in one go in C++ ?

Posted 22 June 2019 - 06:55 PM

Moving to the main C/C++ question forum. The discussion forum is more about the language, rather than for help with coding.
Was This Post Helpful? 1
  • +
  • -

#3 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6969
  • View blog
  • Posts: 23,685
  • Joined: 05-May 12

Re: How to print struct bitfield in one go in C++ ?

Posted 22 June 2019 - 07:12 PM

It doesn't work in C++ because it is very strict about types. reg is declared to be of the type varNode, and there are no predefined stream operators that know about your varNode type. You'll need to override the << stream output operator to print out the information about the structure itself.

I'm just guessing here, because it's been years since I've had to deal with the vagaries of the C printf() function and how variadic functions work. My vague recollections is that for everything from second parameter onwards is put on the stack. So the entire varNode struct is put on the stack. The format specifier (the first parameter) is then parsed to interpret the data that was put on the stack. Since your format specifier "X" says the data type is an integer, it reads the data on the stack as an integer. Since your struct's fields all fit nicely within an integer, then you get the nice side effect of printing out all your bit fields all in one go.

Try changing your struct to something like:
struct varNode {
    uint8_t padding[15];
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};


and see if you get the same result in your C program.
Was This Post Helpful? 1
  • +
  • -

#4 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6969
  • View blog
  • Posts: 23,685
  • Joined: 05-May 12

Re: How to print struct bitfield in one go in C++ ?

Posted 22 June 2019 - 07:23 PM

As an additional thought: If you don't want to override << stream output for your structure, the alternative is to do some pointer magic and static casting. This is a hack.

An evil hack that breaks encapsulation. Assuming that you are using C++ because it is object oriented, then one of the ideas in object oriented programming is the idea of encapsulation. With encapsulation, you shouldn't know how the internals of a class is implemented. That gives the author of the class the latitude to change the internal implementation (perhaps to give you a performance boost, or for him/her to put in some performance telemetry) without you having to change your code. If you start making assumptions about how the class internals implemented (like with the pointer magic and static casting I mentioned above), then your code will break if the class implementation changes and the location of the data that you assumed was at the beginning of the class has moved elsewhere (like with me example about of adding the padding to your struct).
Was This Post Helpful? 1
  • +
  • -

#5 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 01:47 AM

View PostSkydiver, on 22 June 2019 - 07:12 PM, said:

It doesn't work in C++ because it is very strict about types.


OK, reading your answer, so there are really fundamental differences between C and C++. This of course would be one of those issues.

I thought C++ is just C with the new features; like, classes, templates ... etc. But here I think printing out things won't be the same. The iostream in C++ is different than stdio in C. Also with using the boost/format library, it didn't work too.


Quote

reg is declared to be of the type varNode, and there are no predefined stream operators that know about your varNode type.


So, you mean here that stream operators doesn't have predefined function that can print the complete struct variable without including the member of the struct? I think this is the problem here. That the operator "<<" didn't defined to print the struct in one go.

Quote

You'll need to override the << stream output operator to print out the information about the structure itself.
How? I'm really don't have any idea of how manuver things in C++, even in C, I consider myself a beginner in programming world, even I've been practicing for like 4-5 years.



Quote

I'm just guessing here, because it's been years since I've had to deal with the vagaries of the C printf() function and how variadic functions work. My vague recollections is that for everything from second parameter onwards is put on the stack. So the entire varNode struct is put on the stack. The format specifier (the first parameter) is then parsed to interpret the data that was put on the stack. Since your format specifier "X" says the data type is an integer, it reads the data on the stack as an integer. Since your struct's fields all fit nicely within an integer, then you get the nice side effect of printing out all your bit fields all in one go.


Is this explanation of how C deal with the struct ? But I don't have a problem with the code in C. Of course it's nice to know how the compiler is dealing with the struct.

So what about the C++ code? Because that is my problem now.

Quote

Try changing your struct to something like:
struct varNode {
    uint8_t padding[15];
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};



I'm sorry I didn't express that clearly! I don't want a solution for my C code because it works ok. I need a solution for the C++ version, and I just want to learn how to solve this problem and of course that important to me to discover how can I deal with this issue in future.

This post has been edited by wolfrose: 23 June 2019 - 01:56 AM

Was This Post Helpful? 0
  • +
  • -

#6 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 01:55 AM

View PostSkydiver, on 22 June 2019 - 07:23 PM, said:

As an additional thought: If you don't want to override << stream output for your structure, the alternative is to do some pointer magic and static casting. This is a hack.

An evil hack that breaks encapsulation. Assuming that you are using C++ because it is object oriented, then one of the ideas in object oriented programming is the idea of encapsulation. With encapsulation, you shouldn't know how the internals of a class is implemented. That gives the author of the class the latitude to change the internal implementation (perhaps to give you a performance boost, or for him/her to put in some performance telemetry) without you having to change your code. If you start making assumptions about how the class internals implemented (like with the pointer magic and static casting I mentioned above), then your code will break if the class implementation changes and the location of the data that you assumed was at the beginning of the class has moved elsewhere (like with me example about of adding the padding to your struct).


Actually the whole point of learning this problem, is that in embedded programming, there are registers that are 8-bits for the basic line microcontrollers. So I thought to develop a struct bitfield that has a size of 1-byte. And it's just an easy way or a nice programming technique to work with bits. That's my main goal.

So with the example you provided it has a padding of 15, that's extra 15 bytes. And it's not an optimized way in programming microcontrollers.

I would try to know if I can do the struct bitfield; otherwise, I would get back to direct register manipulation.

Like,
REG1 = 0xEA;
And that's it!


I learned in other websites that I can declare the struct inside a union. But didn't started to work on that technique.
Was This Post Helpful? 0
  • +
  • -

#7 Salem_c   User is online

  • void main'ers are DOOMED
  • member icon

Reputation: 2355
  • View blog
  • Posts: 4,474
  • Joined: 30-May 10

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 02:32 AM

Bit-fields don't even work for the problem you have.

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};


If you have varNode a = { a, b, c };, there is absolutely NO guarantee that you'll end up with ccbbbbaa as the bit-pattern in memory. aabbbbcc is just as plausible. It depends on your compiler vendor.

C99 - 6.7.2.1 Structure and union specifiers said:

An implementation may allocate any addressable storage unit large enough to hold a bit-
field. If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.


Bit-fields are only useful for storing internal data in a compact representation. As soon as you try to interact with the outside world, they're useless.

Bit-fields came from a time when each byte of memory cost $1 (the 1960's). Then anything to save memory was a damn good idea.

As a means of saving memory, it's dubious at best. Sure, you can save a lot if you have large arrays of these structures. But if you only have a single instance of that struct, you've saved exactly 2 bytes.

Then you also need to factor in that every time you try to access a bit-field, there are implied >> << & | ~ operators to bit-fiddle the values into (and out of) the structure (you know, what you would have to do by hand if you were to pack the struct yourself). Most machines do not have the kind of instructions that can do all that work in the same amount of space and the same amount of time as a regular memory access. Your code will end up larger and slower. The last machine I worked on has a 3:1 ratio on the number of instructions it took to access a bit-field compared to a regular struct member.

If you want to use C++, then go all in and start using C++ fully - encapsulation is key.
#include <iostream>
#include <cstdint>
using namespace std;

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
    friend ostream &operator<<(ostream &os, const varNode &v) {
        os << int(v.s1)
           << ","
           << int(v.s2)
           << ","
           << int(v.s3);
        return os;
    }
    void writeToReg() {
        uint8_t r = s1 << 6 | s2 << 2 | s3;
        REG1 = r;
    }
    // other methods to suit.
};

int main ( ) {
    varNode v{1,2,3};
    cout << v << endl;
}


Was This Post Helpful? 1
  • +
  • -

#8 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 03:46 AM

View PostSalem_c, on 23 June 2019 - 02:32 AM, said:

Bit-fields don't even work for the problem you have.


First of all thank you so much for the deep thoughtful answer. As I don't have a deep idea of how C or C++ works with limitations of the language. Or how you could hack things with simple trick to override something.



Quote

If you have varNode a = { a, b, c };, there is absolutely NO guarantee that you'll end up with ccbbbbaa as the bit-pattern in memory. aabbbbcc is just as plausible. It depends on your compiler vendor.


Yep, that would work only in C in this case, but yeah it depends on the compiler.

C99 - 6.7.2.1 Structure and union specifiers said:

An implementation may allocate any addressable storage unit large enough to hold a bit-
field. If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.


Is this the description for C or C++ ? I think it's for C.



Quote

Bit-fields are only useful for storing internal data in a compact representation. As soon as you try to interact with the outside world, they're useless.


Yep, it would be ok, for one time compiled code. But, in embedded world / hobbyist horizon. Like, Arduino platform, there is one compiler for the code, either if I compiled the code in Arduino or Atmel Studio, they have one compiler which is AVR-GCC compiler; so in this case I just have to test the compiler order to prove that is either low-high or high-low order.

Most of libraries I go through don't use this method, they use defined values and just combine it or mask it out.

Like:

#define DDRB _SFR_IO8(0x04)
#define DDB0 0
#define DDB1 1
#define DDB2 2
#define DDB3 3
#define DDB4 4
#define DDB5 5
#define DDB6 6
#define DDB7 7

#define PORTB _SFR_IO8(0x05)
#define PORTB0 0
#define PORTB1 1
#define PORTB2 2
#define PORTB3 3
#define PORTB4 4
#define PORTB5 5
#define PORTB6 6
#define PORTB7 7


Then in application/library code, I combine it with the register address; like,

// this is to set the pins direction
DDRB |= (1<<DDB5); // turn pin5 to be output
DDRB &= ~(1<<DDB5); // turn pin5 to be input

// this is to turn the pin to high/low state
PORTB |= (1<<PORTB5); // turn pin5 to be high volt
PORTB &= ~(1<<PORTB5); // turn pin5 to be low volt


So, clearly, my idea isn't very effective in the programming world, otherwise, professional programmers who wrote the fundamental embedded libraries would have done it in their core libraries.

So it just an idea that I tried to do it, it could be not practical at the end of the day.

Quote

Bit-fields came from a time when each byte of memory cost $1 (the 1960's). Then anything to save memory was a damn good idea.


Yep, most core libraries I've been through don't use very strict memory saving approaches for their coding system.

As the code I copied from the AVR microcontroller library, they used a defined byte for each bit number, so it does not matter actually.

Quote

As a means of saving memory, it's dubious at best. Sure, you can save a lot if you have large arrays of these structures. But if you only have a single instance of that struct, you've saved exactly 2 bytes.


You're right for a small library that deals with several configuration registers that have bit-setting configurations, it really doesn't matter to save the names of the bits in defined area or put it inside a struct bitfield as I tried to do, it won't save much!


Quote

Then you also need to factor in that every time you try to access a bit-field, there are implied >> << & | ~ operators to bit-fiddle the values into (and out of) the structure (you know, what you would have to do by hand if you were to pack the struct yourself). Most machines do not have the kind of instructions that can do all that work in the same amount of space and the same amount of time as a regular memory access. Your code will end up larger and slower.


You're right, I even don't know if C++ compilers for the embedded programming IDEs would have these optimizations to deal with bitfields.

Quote

The last machine I worked on has a 3:1 ratio on the number of instructions it took to access a bit-field compared to a regular struct member.


What does that mean? Do you mean that bitfields take more cpu cycles to access them?

Does that mean the approach found in embedded libraries that I copied above are the way to go? They didn't use bitfield, I think that means it isn't an optimized way to deal with 8-bit registers.



Quote

If you want to use C++, then go all in and start using C++ fully - encapsulation is key.
#include <iostream>
#include <cstdint>
using namespace std;

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
    friend ostream &operator<<(ostream &os, const varNode &v) {
        os << int(v.s1)
           << ","
           << int(v.s2)
           << ","
           << int(v.s3);
        return os;
    }
    void writeToReg() {
        uint8_t r = s1 << 6 | s2 << 2 | s3;
        REG1 = r;
    }
    // other methods to suit.
};

int main ( ) {
    varNode v{1,2,3};
    cout << v << endl;
}



Yep, actually that's a lot of work to just mask specific bits in a 8-bit register. I could just define the bits and mask them out with the register, like I did above.


==================================================================================================

You know what as I thought, maybe this isn't an effective way to use the bitfields.

But are bitfields useful now? Do they have important uses in modern programming?
Was This Post Helpful? 0
  • +
  • -

#9 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 04:03 AM

I did this code as as simple solution to get away with something :)

#include <iostream>
#include <string>
#include <fstream>
#include  <iomanip>
#include <boost/format.hpp>

using namespace std;


struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};


int main () {

cout << sizeof(varNode) << endl;

struct varNode reg1;

reg1.s1 = 0x02;
reg1.s2 = 0x07;
reg1.s3 = 0x01;

uint8_t p = reg1.s1 | reg1.s2 << 2 | reg1.s3 << 6;

cout << "0x" << setfill('0') << setw(2) << hex << +p << endl;

  return 0;
}


I think it's a a compiler proof way to wrap my code. What you think ?
Was This Post Helpful? 0
  • +
  • -

#10 baavgai   User is online

  • Dreaming Coder
  • member icon


Reputation: 7448
  • View blog
  • Posts: 15,442
  • Joined: 16-October 07

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 05:36 AM

As an aside, and a silly, you could use a union for that decode:
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>

using namespace std;

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};

union VarNodeN {
    varNode reg;
    uint8_t n;
};

int main() {

    cout << sizeof(varNode) << endl;

    varNode reg1;
    reg1.s1 = 0x02;
    reg1.s2 = 0x07;
    reg1.s3 = 0x01;

    VarNodeN p = {reg1};

    cout << "0x" << setfill('0') << setw(2) << hex << (unsigned)p.n << endl;

    return 0;
}



However, if you're willing to shift bits about, why even bother with the struct?
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>


typedef uint8_t BitSilly;

BitSilly initBitSilly(uint8_t s1, uint8_t s2, uint8_t s3) {
    return (s1 & 3) | ((s2 & 7) << 2) | ((s3 & 3) << 6);
}

int main() {
    BitSilly reg1 = initBitSilly(0x02, 0x07, 0x01);
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)reg1 << std::endl;

    return 0;
}



Though, honestly, for this, a little C++ will probably make your life easier:
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>

struct BitSilly {
    uint8_t n;
    BitSilly() : n(0) { }
    BitSilly(uint8_t x) : n(x) { }
    BitSilly(uint8_t s1, uint8_t s2, uint8_t s3) : n((s1 & 3) | ((s2 & 7) << 2) | ((s3 & 3) << 6)) { }
    void print(std::ostream &out) const {
        out << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)n;
    }
    uint8_t s1() const { return n & 3; }
};

int main() {
    BitSilly reg1(0x02, 0x07, 0x01);
    reg1.print(std::cout);
    std::cout << std::endl;
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)reg1.s1() << std::endl;

    return 0;
}



Hope this helps.
Was This Post Helpful? 1
  • +
  • -

#11 wolfrose   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 56
  • Joined: 20-January 16

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 08:10 AM

View Postbaavgai, on 23 June 2019 - 05:36 AM, said:




Hi, thanks for the answers.

I tried the union and it's a nice way to mask that struct.

I did this code, but everytime I do a change to the reg, it doesn't update the union variable and I have to update it manually. Is there a solution for that?

#include <iostream>
#include <string>
#include <fstream>
#include  <iomanip>
#include <boost/format.hpp>

using namespace std;


struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};

union varMask {
    varNode reg;
    uint8_t mask;
};


int main () {

cout << sizeof(varNode) << endl;

struct varNode reg1;

reg1.s1 = 0x02;
reg1.s2 = 0x07;
reg1.s3 = 0x01;

varMask p;

p = {reg1};

cout << "0x" << setfill('0') << setw(2) << hex << +p.mask << endl;

reg1.s1 = 0x01;
reg1.s2 = 0x01;
reg1.s3 = 0x01;

p = {reg1};


cout << "0x" << setfill('0') << setw(2) << hex << +p.mask << endl;

  return 0;
}




Quote

However, if you're willing to shift bits about, why even bother with the struct?
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>


typedef uint8_t BitSilly;

BitSilly initBitSilly(uint8_t s1, uint8_t s2, uint8_t s3) {
    return (s1 & 3) | ((s2 & 7) << 2) | ((s3 & 3) << 6);
}

int main() {
    BitSilly reg1 = initBitSilly(0x02, 0x07, 0x01);
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)reg1 << std::endl;

    return 0;
}



That's a nice way to set the bits to the required form, but embedded world, each SFR has it's own set of configuration bits. So the arrangement of these bits isn't the same along all the SFR bit.

Maybe my whole point isn't practical. Actually programmers, do the SFRs settings with defined values and just mask the values out with the SFRs using logic operators.

I just learned that there's no point after all of learning how to get away with a trick to set the SFRs using structs. Because I have to develop a struct for each SFR and that is a waste of memory and programmer's time.

But this trick could work with something that isn't related to all the SFR set, but for something that is used frequently in the application/library code.


Quote

Though, honestly, for this, a little C++ will probably make your life easier:
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>

struct BitSilly {
    uint8_t n;
    BitSilly() : n(0) { }
    BitSilly(uint8_t x) : n(x) { }
    BitSilly(uint8_t s1, uint8_t s2, uint8_t s3) : n((s1 & 3) | ((s2 & 7) << 2) | ((s3 & 3) << 6)) { }
    void print(std::ostream &out) const {
        out << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)n;
    }
    uint8_t s1() const { return n & 3; }
};

int main() {
    BitSilly reg1(0x02, 0x07, 0x01);
    reg1.print(std::cout);
    std::cout << std::endl;
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)reg1.s1() << std::endl;

    return 0;
}



Hope this helps.



lol, you're right that's absolutely a bitsilly question :)/>/>/>/> I better start developing my class learning course, then move to templates, if they are useful in embedded programming.

But in embedded programming, like, in Arduino platform that is mostly done in C++, I really like, the skills and the features of inheritance and using of classes/friend class/public class.

I'm still in the area, of discovering the fundamentals AND the advantages/features of C/C++.

====================================================================================================================

This is an off topic question, should I open a new thread about it?
I want to know what is the difference between static/shared/dynamic libraries. I learned how to set them up in codeblocks recently and how to link them basically. But I want to know which type should I use and which type fit certain programming purposes.

This post has been edited by wolfrose: 23 June 2019 - 08:13 AM

Was This Post Helpful? 0
  • +
  • -

#12 baavgai   User is online

  • Dreaming Coder
  • member icon


Reputation: 7448
  • View blog
  • Posts: 15,442
  • Joined: 16-October 07

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 09:37 AM

View Postwolfrose, on 23 June 2019 - 10:10 AM, said:

I did this code, but everytime I do a change to the reg, it doesn't update the union variable and I have to update it manually. Is there a solution for that?

Of course. One would be to mate the two structs into one. e.g.
typedef union {
    struct {
        uint8_t s1 : 2;
        uint8_t s2 : 4;
        uint8_t s3 : 2;
    } segs;
    uint8_t n;
} BitBetter ;

int main() {
    BitBetter reg1;

    reg1.segs.s1 = 0x02;
    reg1.segs.s2 = 0x07;
    reg1.segs.s3 = 0x01;



However, really, make the code do the work. Perhaps something like:
#include <fstream>
#include <iomanip>
#include <iostream>

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};

union varMask {
    varNode reg;
    uint8_t mask;
    varMask() {}
    varMask(const varNode &x) { reg = x; }
    varMask(uint8_t x) : mask(x) {}
};

void showHex(uint8_t n) {
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)n;
}
void showHex(const varMask &x) { showHex(x.mask); }
void showHex(const varNode &x) { showHex(varMask(x)); }

void showHexBits(const varNode &x) {
    showHex(x.s1); std::cout << ' '; showHex(x.s2); std::cout << ' '; showHex(x.s3);
}

varNode &setValues(varNode &x, uint8_t s1, uint8_t s2, uint8_t s3) {
    x.s1 = s1; x.s2 = s2; x.s3 = s3; return x;
}

int main() {
    varNode reg1;
    std::cout << sizeof(reg1) << std::endl;

    showHex(setValues(reg1, 0x02, 0x07, 0x01)); std::cout<< std::endl;
    showHexBits(reg1); std::cout << std::endl;
    showHex(setValues(reg1, 0x01, 0x01, 0x01)); std::cout<< std::endl;
    showHexBits(reg1); std::cout<< std::endl;

    return 0;
}



Results:
1
0x5e
0x02 0x07 0x01
0x45
0x01 0x01 0x01



It should be noted that you needn't use that union trick at all: it's just something that naturally flows from those bit slices you're using. You can just cast the thing. e.g.
#include <fstream>
#include <iomanip>
#include <iostream>

struct varNode {
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};

void showHex(uint8_t n) {
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)n;
}

void showHex(const varNode &x) {
    uint8_t n(*(uint8_t *)&x);
    showHex(n);
}

void showHexBits(const varNode &x) {
    showHex(x.s1); std::cout << ' '; showHex(x.s2); std::cout << ' '; showHex(x.s3);
}

varNode &setValues(varNode &x, uint8_t s1, uint8_t s2, uint8_t s3) {
    x.s1 = s1; x.s2 = s2; x.s3 = s3; return x;
}

int main() {
    varNode reg1;
    std::cout << sizeof(reg1) << std::endl;

    showHex(setValues(reg1, 0x02, 0x07, 0x01)); std::cout<< std::endl;
    showHexBits(reg1); std::cout << std::endl;
    showHex(setValues(reg1, 0x01, 0x01, 0x01)); std::cout<< std::endl;
    showHexBits(reg1); std::cout<< std::endl;

    return 0;
}



Union causes the same storage to be used for multiple storage shapes. If your goal is simply to look at that storage in a different shape, you can cast your way to type unsafety. Which might be more useful to you. e.g.
#include <fstream>
#include <iomanip>
#include <iostream>


void showHex(uint8_t n) {
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << (unsigned)n;
}

int main() {
    struct {
        uint8_t s1 : 2;
        uint8_t s2 : 4;
        uint8_t s3 : 2;
    } x =  { 0x02, 0x07, 0x01 };
    showHex(x.s1); std::cout << ' '; showHex(x.s2); std::cout << ' '; showHex(x.s3); std::cout << std::endl;

    // make is a generic pointer
    void *p = &x;
    // cast that pointer
    uint8_t *np = (uint8_t *)p;
    // get something solid
    uint8_t n = *np;
    showHex(n);  std::cout<< std::endl;

    return 0;
}


This post has been edited by baavgai: 23 June 2019 - 09:38 AM
Reason for edit:: code tag fail

Was This Post Helpful? 0
  • +
  • -

#13 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6969
  • View blog
  • Posts: 23,685
  • Joined: 05-May 12

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 10:42 AM

View Postwolfrose, on 23 June 2019 - 04:47 AM, said:

Quote

Try changing your struct to something like:
struct varNode {
    uint8_t padding[15];
    uint8_t s1 : 2;
    uint8_t s2 : 4;
    uint8_t s3 : 2;
};



I'm sorry I didn't express that clearly! I don't want a solution for my C code because it works ok. I need a solution for the C++ version, and I just want to learn how to solve this problem and of course that important to me to discover how can I deal with this issue in future.

I was trying to demonstrate that your C code was just working by accident. C doesn't know how to print out a structure the same way C++ doesn't know how to print out a structure. It so happened that the copy of the struct put on the stack fit into the space occupied by an integer, and then your printf() format specifier said that the parameter on the stack is an integer. By making the structure bigger than an integer, I was trying to show that now you'll get junk/random values from within the padding instead of from your bit fields.
Was This Post Helpful? 1
  • +
  • -

#14 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6969
  • View blog
  • Posts: 23,685
  • Joined: 05-May 12

Re: How to print struct bitfield in one go in C++ ?

Posted 23 June 2019 - 11:41 AM

It seems like what you are looking for is a helper to make flipping bits on a I/O port or register more readable.

Off the top of my head, it seems that by using placement new and the following class may help make code more legible instead of looking at all those bit twiddling:
class Register {
public:
    inline uint_8 Get() const {
        return m_sfr;
    }

    inline void Set(uint_8 value) {
        m_sfr = value;
    }

    inline uint_8 GetMasked(uint_8 mask) const {
        return m_sfr & mask;
    }

    inline void SetBitMask(uint_8 mask) {
        m_sfr |= mask;
    }

    inline void ClearBitMask(uint_8 mask) {
        m_sfr &= ~mask;
    }

    inline void FlipBitMask(uint_8 mask) {
        m_sfr ^= mask;
    }

    inline bool GetBit(int bit) const {
        return !!(m_sfr & (1 << bit));
    }

    inline void SetBit(int bit) {
        m_sfr |= (1 << bit);
    }

    inline void ClearBit(int bit) {
        m_sfr &= ~(1 << bit);
    }

    inline void FlipBit(int bit) {
        m_sfr ^= (1 << bit);
    }

private:
    volatile uint_8 m_sfr;
};

// Placement new
inline void * operator new(size_t cbSize, volatile uint_8 * pv) {
    return pv;
}

:

Register * ddrb = new (DDRB) Register();
ddrb->SetBit(DDB1);
if (ddrb->GetBit(DDB7)) {
    // do something
}
ddrb->FlipBits(0xAA);
cout << "DDRB is current set to: " << ddrb->Get() << endl;



The reason why we want to use the placement new is so that the class Register is placed over the port or register whose bits are to be manipulated. The reason for the class is just to provide more readable/legible methods than trying to understand (or paying close attention to) the operation being performed on the port/register.

Once you have this basic build block of the Register class, then you can build up a more semantic set of classes over it. Something like this completely hypothetical class (since I know nothing about Arduino ports):
class Motor {
public:
    Motor() : m_port1(new (PORT1) Register()){
    }

    void Start() {
        m_port1->SetBit(PORT1B0);
    }

    void Stop() {
        m_port1->ClearBit(PORT1B0);
    }

private:
    Register * m_port1;
}

:

Motor motor;
motor.Start();


Was This Post Helpful? 1
  • +
  • -

Page 1 of 1