3

Some preprocessor macros I come across have arguments with names containing a leading underscore; for example, in the Linux kernel:

#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

These arguments appear to behave just like regular macro arguments, so I can't figure out why the author decided to have a leading underscore for each argument name. Is there some significance to the concatenation with _name, or are the underscores just a convention the author chose to use?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
  • 2
    @H2CO3 the ones that start with an underscore followed by a lowercase letter [should be OK](http://stackoverflow.com/q/1449181/335858), only the `__ATTR` is suspicious. – Sergey Kalinichenko Apr 29 '13 at 20:16
  • 3
    @dasblinkenlight That answer states (quote from the Standard): "All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces" - for me, that counts as reserved too. –  Apr 29 '13 at 20:18
  • 4
    @H2CO3 But macro parameters are not identifiers. So it may be irritating, but doesn't infringe any reservations, as far as I can tell. – Daniel Fischer Apr 29 '13 at 20:27
  • 1
    The OS also wishes to hide implementation details from the *user space*. Some kernel headers are meant to be exported to *user space* and they are prefix with underscores to avoid name clashes. This information is available, with a cursory look. See also [headers_check.pl](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/scripts/headers_check.pl) The use of **POSIX** in the kernel is frowned upon ;-) You are asking a lot of linux kernel questions. [Vilhelm's Linux kernel questions](http://stackoverflow.com/search?q=user:1806289%20[linux-kernel]%20is:question) – artless noise Apr 29 '13 at 20:31
  • @DanielFischer Right. That's too bad, it really should. –  Apr 29 '13 at 20:42
  • @artlessnoise I've been programming for years in standards-compliant C with a personal focus on portability, but this is the first time I've taken a crack at coding specifically for the Linux kernel. The exposure to system-level source code has been one of the most enlightening experiences I've had in a while, so I've naturally been determined to make sense of anything that seems out of place at first glance! :-) – Vilhelm Gray Apr 29 '13 at 20:45
  • You shouldn't tag *linux-kernel* questions with *c*. The *linux-kernel* can only be compiled with `gcc`; hence it is only as portable as `gcc`. All of your *linux-kernel* questions seem to be tagged with **C**; I think you will do better to omit the **C** tag **most** of the time; especially if you are referring to kernel source proper (ie, not external APIs). – artless noise Apr 29 '13 at 20:51
  • I see, I didn't realize the kernel was so dependent on `gcc`; is this dependence due to all the GCC-specific code (for example `__attribute__`)? – Vilhelm Gray Apr 29 '13 at 20:57
  • 1
    Yes of course *attributes* are `gcc` specific. There are lots of linker section hacks and other oddities you will find that are not *standard C* (for example `init_call`, etc). I like Edward D. Willink's [Fog thesis](http://www.computing.surrey.ac.uk/research/dsrg/fog/FogThesis.pdf). Part of it describes systemic design patterns; ie, things you find every where in source. There is lots of infra-structure that bend the rules in Linux. Just like code generation tools; Qt's `moc`, *c-front*, *kbuild*, etc. This is especially easy with the GNU tools, pipes and other Unix shell philosophy. – artless noise Apr 29 '13 at 21:14
  • @artlessnoise: I disagree. The Linux kernel is (mostly) written in C. It happens not to be *portable* C, but it's still C. – Keith Thompson Apr 29 '13 at 21:25
  • @KeithThompson Almost all Linux software is *C*, does that mean it should be tagged with *C*? I didn't say **ALL** *linux-kernel* question should not be tagged with *C*, I explicitly said **most**. Every single question Vilhelm has posted with the *linux-kernel* tag has been tagged with *C*. In particular, I don't think this question is using anything that bends the *C* language rules. Do you really think it is appropriate for this particular question? I may have been a little too strong, but I really think that not **every** Linux kernel question needs a *C* tag; even if it is coded in C – artless noise Apr 29 '13 at 22:20
  • @artlessnoise: I see two lines of C source code and a question about that code. Yes, this question absolutely should be tagged C, and I'm at a loss to understand why you think it shouldn't. I don't know what you mean by "anything that bends the C language rules". I'm not talking about "**every** Linux kernel question", just about this one. (You wouldn't be thinking of the comp.lang.c topicality guidelines, would you? If so, they don't apply here.) – Keith Thompson Apr 29 '13 at 22:49
  • @KeithThompson I expect it runs on a [tag:cpu] and uses [tag:memory]. – artless noise Apr 29 '13 at 23:02
  • @artlessnoise: The question is specifically about C source code. By your criteria, should *any* question be tagged **C**? – Keith Thompson Apr 29 '13 at 23:18
  • @KeithThompson Actually, the question seems to be about the *thoughts* of the code's author, as I read it. There are lots of questions that can be tagged with **C**, if they are specifically about the **C** language or how to solve a problem in **C**, not just that something is coded in **C**. I guess we disagree. – artless noise Apr 30 '13 at 00:03

1 Answers1

2

No, there is no special significance: these are regular identifiers. My guess as to why the authors decided to add underscores like that is to make the composition of these attributes more legible:

dev_attr_##_name

is easier to read than

dev_attr##name

The __ATTR, however, looks suspicious: in C, identifiers that start in an underscore followed by an uppercase letter or another underscore, are reserved for the implementation. In this case, it's two underscores, so I would expect __ATTR to be a system macro.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • `__ATTR` similarly confuses me, yet the source code apparently has a definition: http://lxr.free-electrons.com/source/include/linux/sysfs.h?v=3.2#L70 – Vilhelm Gray Apr 29 '13 at 20:23
  • 3
    @VilhelmGray If it comes from the device drivers headers, it should be OK: these are intimately attached to the system for which they are compiled; at any rate, they are not intended for portability. – Sergey Kalinichenko Apr 29 '13 at 20:27
  • 2
    Linux is part of *the implementation*. `gcc` is usually identified by a *tuple* or [GNU triplets](http://wiki.debian.org/Multiarch/Tuples); the *OS*, *libc* and *code generators* are usually part of *the implementation*. The *OS*, *libc* and *code generators* need to co-ordinate so that they do not trample on each others symbols. *OS* code is intrinsically non-portable. A quick look at *sysfs.h* shows that it is using *designated inits* and the `_xxx` is being assigned to the structure member `xxx`; if the names were identical, the macro would not work. – artless noise Apr 30 '13 at 14:26