C - Double underscore inside of #define macro

3

I have done some searching and have consulted a friend of mine, but also want to get the StackExchange's communities input. To preface I'm mainly a HW person who has been slammed into low-level firmware land, so forgive me for anything that seems as common knowledge. I have done C programming in the past, but it has been a while.

For a custom ASIC I am apart of we have many control/status registers that we will access through software/firmware (I will likely just call it SW from now on). For our verilog/SV/UVM testbenchs, we have a script that builds a verilog header `define file. In this case we have the following structure:

`define REG_NAME                        <addr of register>
`define REG_NAME__BITFIELD1             <bit vector i.e. 1:0>
`deinfe REG_NAME__BITFIELD2             <bit vector i.e. 4:2>

We use a double underscore to distinguish visually between the register name and bitfield. We then use this for doing things like read-modify-writes, masking out bits, etc. For the SW, I wrote a script to print out a .h file in C format. I wanted to keep a similar formatting:

#define REG_NAME                        <addr of register>
#define REG_NAME__BITFIELD1___MASK      0x00000003
#define REG_NAME__BITFIELD1___SHIFT     0
#deinfe REG_NAME__BITFIELD2___MASK      0x0000001c        
#deinfe REG_NAME__BITFIELD2___SHIFT     2

In this case I want to maintain the double underscore for the distinction between the REG and BIT_FIELD and the triple to distinguish the MASK/SHIFT/anything else I add.

I know based on the following SE questions: Use of double underscore in C How is __mro__ different from other double underscore names?

That prefixed underscores is not a good coding practice. Is it generally a bad coding practice to have double/triple underscores INSIDE of the define like this? I know that I could control the macro define to never start with or end with the double/triple underscore. It's honestly something that aids me quite a bit. I have a hard time picking out the differences between words when all single underscores are used. And with there being over 60k #defines based on registers, I would like to have a cleaner way to look at it. However if this is something that most SW engineers would barf at, I would change it as sooner or later (hopefully) someone who is a real SW engineer will be handling most of this (not that I mind doing SW, it's fun).

If this has been discussed, please feel free to forward the thread. I searched around for about 30-45 mins, but could not find anything that seemed to discuss this topic exactly.

Thanks!

c
asked on Stack Overflow Apr 18, 2017 by l Steveo l • edited May 23, 2017 by Community

1 Answer

5

In both C and C++, you (the application programmer) should avoid beginning identifiers with even a single underscore - all such identifiers are "reserved for the implementation" in at least some contexts; rather than remember the exact rules it's easiest to just stick to starting all your identifiers with a letter.

In C++ only, identifiers that contain two consecutive underscores (like your REG_NAME__BITFIELD1___MASK) are also reserved for the implementation.

So, as far as the standard is concerned, you can do what you want in C, but not in C++.

As a matter of style, I personally think your rationale for wanting to use two underscores in a row (lots of similar identifiers with structure in their names, make the structure more obvious) is legitimate, and I don't agree with the people in the linked question who say it's too hard to tell the difference between one and two underscores, when reading. I don't understand why you want three underscores in a row, though, and I do think it's too hard to tell the difference between two and three underscores in a row.

(Note: one of the old questions you linked to is about Python, which is a completely unrelated language; it cannot be used to draw conclusions about C or C++.)

(You can use identifiers defined by the implementation that begin with an underscore, as long as they are documented—e.g. __STDC__, _Bool, _IOLBF—just don't ever define them yourself, unless the documentation specifically tells you to define them (e.g. _POSIX_C_SOURCE). In complicated programs, the line between "the program" and "the implementation" can get blurry, so don't freak out if you see a program defining identifiers that begin with an underscore; there's a good chance that the authors know precisely what they are doing.)

answered on Stack Overflow Apr 18, 2017 by zwol • edited Apr 18, 2017 by zwol

User contributions licensed under CC BY-SA 3.0