3 ms·
> you must waste extra time to check each function definition to see whether it does the right thing I think I see what you're arguing. That this: reg1 &=
by kennywinker 5y ago
> you must waste extra time to check each function definition to see whether it does the right thing
I think I see what you're arguing. That this:
reg1 &= ~(width_mask_1 << shift);
reg2 &= ~(width_mask_2 << shift);
reg3 &= ~(width_mask_3 << shift);
// etc...
is clearer than something like this:
reg1 = ClearBitField(reg1, 1, shift);
reg2 = ClearBitField(reg2, 2, shift);
reg3 = ClearBitField(reg3, 3, shift);
// etc...
If that's what you're arguing, I simply don't agree. `ClearBitField` is descriptive and readable. It avoids creating all those width_mask_n constants, since you specify the width as input to the fn. You don't have to go digging into `ClearBitField` because you wrote a unit test to confirm that it does what it says on the label and handles the edge cases.
On top of that, the code inside `ClearBitField` can be as verbose or as compact as you desire, because it's contained and separated from the rest of the code.
- adrian_b 5y agoObviously this is a matter of personal preferences and experience. Real register names are usually very long, to indicate their purpose, so you would not want to repeat them on each line. This can be avoided by redefining ClearBitField. Even so, writing an extra "ClearBitField" on each line does not provide any information. It just clutters the space. Anyone working with such code is very aware that &=~ means clear bits and |= means set bits. When reading the table of names, the repeated function name is just a distraction that is harder to overlook than the operators. The way to improve over that is not adding anything on the lines, but using simpler symbols by defining the registers as structures, i.e.: register_1 . bit_field_1 = constant_name_1; register_2 . bit_field_2 = constant_name_2; register_3 . bit_field_3 = constant_name_3; Unfortunately, like I have said, the hardware vendors seldom provide header files with structure definitions for the registers and rewriting the headers is a huge work. However, if you are able to rewrite just the register definitions that you use, that would be better spent time than attempting to write functions or macros for these tasks.
- fouric 5y agoI find the first code example easier to read and process. However, that's because I've written a fair bit of C code, and so when my brain goes into "C mode", the symbols &, =, ~, <<, etc. all have clear and unambiguous meanings - whereas ClearBitField does not. Additionally, the pattern ~(foo << bar) is a common C idiom, so beyond the individual symbols, my brain recognizes the whole pattern so it's "semantically compressed" (easier to think about) for me. This would not be the case for a beginner. Which style is better depends on an individual's preferences and experiences - there's no "right" answer. This is a stellar example of one of the many reasons why code-as-text is a huge mistake - because structure and representation are conflated and coupled together. A sanely written programming language represents code as code objects, and you can configure those code objects to be displayed however you like, whether that's baz &= ~(foo << bar) or ClearBitField(baz, 1, bar).