24

In some C projects, function names start with a common prefix indicative of the module name, for example:

mymodule_do_this_stuff();

mymodule_do_that_stuff();

Is there a justification for doing so when the linkage is internal, and there is no possibility of namespace collisions?

For example,

static void mymodule_do_this_stuff(void)
{
  ...
}
ilkkachu
  • 151
  • 6
user6007354
  • 351
  • 2
  • 5
  • 9
    Because C does not have namespaces, packages or any other name scoping mechanism. Prefixing with a module name simulates a namespace. – Robert Harvey Feb 04 '20 at 14:47

3 Answers3

40

Why prefixes in the first place?

The prefix for function names is a C practice that intends to avoid naming conflicts.

This is especially suitable in big projects, where different teams could easily come with do_this() and do_that() in different subcomponents of a large codebase.

Since C lacks of a namespace or a package feature, the prefix is the most common workaround. It’s not the only workaround: There are other approaches , but with their own drawbacks.

Does it make sense for static functions?

Of course, prefixing internal static functions does not reduce any naming conflict. This is a side effect of the prefix scheme decided in the first place.

The reasons that justifies this practice are:

  • consistency in the naming scheme: if 80% of the time you use a prefix, not having it on the 20% remaining functions might cause more confusion than you’d expect.
  • flexibility in the evolution: bear in mind that all static functions were not necessarily static from their inception. static or not static is something that could change over time. And mixing prefixed and unprefixed name could make such natural changes more painful than necessary.
Christophe
  • 74,672
  • 10
  • 115
  • 187
  • 34
    Prefixing internal static functions _does_ still reduce naming conflict. If I call my internal function `do_this`, I can't include another function `do_this` from a badly-written 3rd-party library. It's as much to defend me from existing code as it is to improve my code in itself. – Useless Feb 03 '20 at 16:20
  • 2
    @Useless Thank you for this remark! that’s definitively one more argument in favour of the consistent use of that scheme ! – Christophe Feb 03 '20 at 17:05
  • 3
    Some implementations handle static symbols by attaching a module-specific prefix and then exporting them. This allows such symbols to be included within debug information, symbol maps, etc. and may also simplify the compiler by allowing it to let the linker fix up internal references the same way as external ones. If both widget and woozle have a static object named `foo`, having the map file list `__XUY1931_foo` and `__XUY198921_foo` may be less useful than `__XUY1931_widget_foo` and `__XUY198921_woozle_foo`. – supercat Feb 03 '20 at 20:13
  • 1
    @supercat interesting remark! Thanks! To be added to the already long list of arguments ;-) – Christophe Feb 03 '20 at 20:51
  • "all `static` functions were not static from their inception" Well, definitely not in the code I write. I usually treat `static` functions as pure implementation details of the module/class files that contain them, designing them from the off not to be shared with other code. I cannot recall adding a single `static` afterwards without the omission being a mistake in the first place. Probably I'm the minority with this, but my approach definitely exists... – cmaster - reinstate monica Feb 04 '20 at 09:45
  • 1
    @cmaster-reinstatemonica: There are times when I've exposed a parameter as an exported object as the simplest way of allowing client code to control it, and the later decided that the amount of client code using it was small enough, and the advantages of controlling access would be sufficient, that I've changed the object to `static` and added explicit functions to access it. – supercat Feb 04 '20 at 15:26
  • @supercat I do not doubt that this happens. I just took offense with the "*all*". Because I happen to write static functions that never had external linkage. Saying "all `static` functions were not static from their inception" sounds to me like saying "all `private` members were not private from their inception". I believe that it should be the normal case that `private` members are declared `private` from the off, just like `static` functions are declared `static` from the off. Of course, there are exceptions to this, but that's the rule I try to adhere to. – cmaster - reinstate monica Feb 04 '20 at 16:13
  • @cmaster-reinstatemonica: If I'm writing code on an embedded platform where space is going to be tight, and expanding requirements may make it necessary to refactor code to make it smaller, `modeFlag |= 2;` may be more compact than `setMode(getMode() | 2);` On the other hand, if many places do that, replacing them with `setModeBits(2);` may be more compact yet. – supercat Feb 04 '20 at 16:30
  • @cmaster-reinstatemonica no offense. In fact, I think we do not disagree: I meant to say that « not all static » but it felt weird so I used an inversion to write « all .. not » hoping for a better style. But I’m not English native.... The point is that some are static or non static from the scratch and do not change (majority?). Some change in the course of the development (a couple?). – Christophe Feb 04 '20 at 17:33
  • Well, the position of the "not" is indeed important. I'll suggest an edit to move the "not" to the front, because as it stands, you are saying that there is not a single `static` function that was designed to be static from the start. With the "not" in front, you are relativating the "all" as you intended to do. – cmaster - reinstate monica Feb 04 '20 at 19:39
  • 1
    @cmaster-reinstatemonica: See https://www.google.com/search?q=all+that+glitters+is+not+gold. (Though I agree that in Present-Day English it's more common to say "not all X do Y" than "all X don't Y".) – ruakh Feb 04 '20 at 19:56
  • @ruakh (Note to self: Never ever assume I've understood the rules of a natural language.) You are right, now that you mention it, I actually remember that saying. – cmaster - reinstate monica Feb 04 '20 at 20:52
  • @cmaster-reinstatemonica apparently stackexchange confirms that the wording is correct, even if it might confuse those who parse it like a logical predicate: https://english.stackexchange.com/q/6251/373969 – Christophe Feb 04 '20 at 23:35
  • 1
    @ruakh: Shakespeare's wording was chosen to fit the trochaic tetrameter of the verse in which it appears, rather than for semantic precision. – supercat Feb 05 '20 at 00:16
  • 1
    @supercat: OK, then see https://www.google.com/search?q=%22all+is+not+lost%22, https://www.google.com/search?q=%22all+is+not+as+it+seems%22, https://www.google.com/search?q=%22all+are+not+equal%22 . . . like it or not, wide-scoped negation is a part of English. (The "not all [...]" phrasing is better. But it's idle to suggest that "all [...] not" unambiguously means "no [...]".) – ruakh Feb 05 '20 at 00:35
  • ok point taken. Thank you for this debate about English style: I’ve edited, hoping that more people will understand it with less doubts. I’d appreciate if some native speaker could confirm if the new wording is clearer – Christophe Feb 05 '20 at 00:41
17

There are two important types of naming collisions here. You are correct in that the compiler won't have any trouble differentiating between the functions due to scope rules. Your problem is that you still have collisions inside the programmer's brain.

Think about it this way: if you have 8 modules that all have a process_data() function, and you get a stacktrace that shows a fault inside process_data(), which module generated the fault? Having the module name as a prefix makes it much easier to glance at the names and immediately know which process_data is being referred to without having to do a lot of detective work.

bta
  • 1,003
  • 6
  • 12
16

There is another reason to use prefixed names even for file-local functions: they can be navigated with simple text search and text indexers without full analysis of language scoping, such as id-utils. Given that C projects often have their history going back to 90x and even earlier, it is an important reason.

max630
  • 2,543
  • 1
  • 11
  • 15