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)
{
  ...
}
1
  • 9
    Because C does not have namespaces, packages or any other name scoping mechanism. Prefixing with a module name simulates a namespace. Feb 4, 2020 at 14:47

3 Answers 3

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.
16
  • 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 3, 2020 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 3, 2020 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 3, 2020 at 20:13
  • 1
    @supercat interesting remark! Thanks! To be added to the already long list of arguments ;-)
    – Christophe
    Feb 3, 2020 at 20:51
  • 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 4, 2020 at 15:26
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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.