You are not logged in.
I hate that one of the most difficult challenges to me in programming is naming things.
So I typically use a namespace-ish convention, where symbols are prefixed with the module they belong to. For example, given a widget.h that declares enum widget_status, struct widget, and functions widget_initialize() and widget_terminate(), this might be widget.c:
#include <assert.h>
#include <stdio.h>
#include "widget.h"
#define _PRINT_IT printf("%d widgets now active\n", _widgets_active)
static int _widgets_active;
static void _incr(void)
{
++_widgets_active;
_PRINT_IT;
}
static void _decr(void)
{
--_widgets_active;
_PRINT_IT;
}
enum widget_status widget_initialize(struct widget *w, int x, int y, int z)
{
assert(w);
w->x = x;
w->y = y;
w->z = z;
_incr();
return WIDGET_STATUS_SUCCESS;
}
enum widget_status widget_terminate(struct widget *w)
{
assert(w);
memset(w, 0, sizeof *w);
_decr();
return WIDGET_STATUS_SUCCESS;
}
Obviously the problem here is my using an underscore prefix on the global symbols (_PRINT_IT, _widgets_active, _incr() and _decr()). Several years ago this made sense to me because it followed with my namespace convention, being at the global (static) namespace. Shortly afterwards I learned that this is bad practice because symbols prefixed with an underscore are reserved by standards, but being super stubborn it's taken me this long to finally consider some alternative.
How do you guys identify static global symbols? I've thought about using a "my_" prefix, but that gives me bad dreams of Perl.
Please share your own practices and/or suggestions! Thanks.
Last edited by cmtptr (2012-09-04 17:30:26)
Offline
Be careful about using underscore prefixed names, as this might be encroaching upon libc/compiler territory:
http://gcc.gnu.org/onlinedocs/cpp/Syste … acros.html
Lately I've been thinking about how to adopt Google's C++ style guide to C. You might consider using underscore suffixed names for static globals if they aren't constants (in which case they'd be a kAwesomeConstant).
Last edited by falconindy (2012-08-23 04:13:33)
Offline
I hate that one of the most difficult challenges to me in programming is naming things.
Not just to you. As someone said, there are two hard problems in computer science, caching, naming things and off-by-one errors.
Personally, I see no dire need for prefixes or suffixes at all. At the point where I'm using the function/variable, most of the time I don't really care whether it's visible outside of this translation unit or not, so that's just useless line noise to me, encroaching on Hungarian territory.
Offline
cmtptr wrote:I hate that one of the most difficult challenges to me in programming is naming things.
Not just to you. As someone said, there are two hard problems in computer science, caching, naming things and off-by-one errors.
Personally, I see no dire need for prefixes or suffixes at all. At the point where I'm using the function/variable, most of the time I don't really care whether it's visible outside of this translation unit or not, so that's just useless line noise to me, encroaching on Hungarian territory.
Glad to know I'm not alone!
I have been putting some serious thought into dropping the thing altogether, with the standard "if it isn't immediately obvious from reading the code, then the code is poorly organized or needs to be broken into smaller pieces" logic. I am definitely a newly-converted believer that constructs like this do more harm than good: artificially making code more readable only serves to facilitate bad structure. So this is probably the best way to go, thanks for reinforcing that for me.
It's just hard to let go of something you've been hiding behind for so long. It's like if you woke up one day and suddenly realized that pants haven't been necessary for decades. That first leap of walking outside with no pants on would be hard!
Thanks for the replies.
Offline
Anything with external linkage is foo_* where foo is the name under which I intend to distribute the package (or maybe an abbreviated version).
Internal linkage, pretty much anything goes, but _foo_* is acceptable as long as I can be reasonably sure foo is not something an implementation is likely to use. (_Foo_* is not ok because names beginning with an underscore followed by a capital letter are reserved for the standard, not the implementation.)
No linkage, no prefix.
Offline
For an identifier with translation unit visibility I would rather spend a few extra characters to give it a descriptive name than to lock myself to some prefix.
Offline
For an identifier with translation unit visibility I would rather spend a few extra characters to give it a descriptive name than to lock myself to some prefix.
Oh, definitely. (I'm assuming what you mean by "translation unit visibility" is the same as internal linkage.) Descriptive names, definitely, but it's also nice to have a prefix to make it easier to identify and list objects that are specific to your project (as opposed to those that you might import from other libraries).
Offline
drobole wrote:For an identifier with translation unit visibility I would rather spend a few extra characters to give it a descriptive name than to lock myself to some prefix.
Oh, definitely. (I'm assuming what you mean by "translation unit visibility" is the same as internal linkage.) Descriptive names, definitely, but it's also nice to have a prefix to make it easier to identify and list objects that are specific to your project (as opposed to those that you might import from other libraries).
Internal linkage, yes.
I wouldn't use a general prefix like underscore though, I would rather use something specific for the unit, like db_* in a unit dealing with databases and widget_* in a unit dealing with widgets.
Offline
I thought that reserved named in C started with a double underscore.
Offline
I thought that reserved named in C started with a double underscore.
I believe both the single-underscore and double-underscore prefixes are reserved, but I'm not entirely clear on whether they're both reserved by the same standard and on whether they're both reserved for the implementation. I know that gcc and glibc tend to use the double-underscore for their extensions, but I can't, off the top of my head, think of any single-underscores I've come across personally. In fact, falconindy's link explicitly mentions only the double-underscore prefix and single-underscore-capital-letter namespaces.
I suppose this ambiguity (or misunderstanding on my part) is partly why it has taken me this long to recognize it as bad practice.
Last edited by cmtptr (2012-08-25 13:05:27)
Offline
From C99:
7.1.3 Reserved identifiers
1
Each header declares or defines all identifiers listed in its associated subclause, and
optionally declares or defines identifiers listed in its associated future library directions
subclause and identifiers which are always reserved either for any use or for use as file
scope identifiers.
— All identifiers that begin with an underscore and either an uppercase letter or another
underscore are always reserved for any use.
— 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.
— Each macro name in any of the following subclauses (including the future library
directions) is reserved for use as specified if any of its associated headers is included;
unless explicitly stated otherwise (see 7.1.4).
— All identifiers with external linkage in any of the following subclauses (including the
future library directions) are always reserved for use as identifiers with external
linkage.(157)
— Each identifier with file scope listed in any of the following subclauses (including the
future library directions) is reserved for use as a macro name and as an identifier with
file scope in the same name space if any of its associated headers is included.
2 No other identifiers are reserved.
The way I interpret this standardese, __foo and _Foo are unconditionally reserved -- you may not use them in your program or library because they might be used by the implementation or by current or future versions of the standard. This includes predefined macro names like __FILE__ and __STDC_VERSION__ (everything beginning with __STDC_ is reserved specifically for the standard in 6.11.9), compiler extensions like __attribute__, and names that are currently part of the standard like _Bool and _Complex. (I can't think of any compiler extensions that start with an underscore and a capital letter.)
_foo, on the other hand, is reserved specifically for use as an identifier with file scope... let me think about that. That means you may create and use _foo if it has block scope, i.e. as a variable within any function declared without extern. But you are not allowed to use it as the name of a function or a variable with file scope. (If I'm reading this right.) My usage violates this rule.
Maybe I should adopt a style manual.
Offline
I should start referring to standards more often...
That means you may create and use _foo if it has block scope, i.e. as a variable within any function declared without extern. But you are not allowed to use it as the name of a function or a variable with file scope. (If I'm reading this right.) My usage violates this rule.
But reserved for who? Reserving something at file scope doesn't make any sense for the implementation or for libraries. The user is the only one who writes anything with file scope. I actually interpreted that as confirming your and my usage of the single-underscore prefix (with the exception of my _PRINT macro, because it begins with an underscore and a capital letter).
Last edited by cmtptr (2012-08-25 15:32:59)
Offline
Reserving something at file scope doesn't make any sense for the implementation or for libraries. The user is the only one who writes anything with file scope.
Au contraire, at least according to the way the Standard uses the term (which might be a little weird). File scope is the widest scope available and applies (loosely speaking) to every identifier not declared in a function, including standard-defined ones such as printf and size_t -- scope is indifferent to whether an identifier is defined in a header file or not. Scope is syntactic; linkage is semantic.
Offline
cmtptr wrote:Reserving something at file scope doesn't make any sense for the implementation or for libraries. The user is the only one who writes anything with file scope.
Au contraire, at least according to the way the Standard uses the term (which might be a little weird). File scope is the widest scope available and applies (loosely speaking) to every identifier not declared in a function, including standard-defined ones such as printf and size_t -- scope is indifferent to whether an identifier is defined in a header file or not. Scope is syntactic; linkage is semantic.
Cool, thanks for clearing that up. You caught me mid-editing my previous post; as I reread this sentence I noticed it also conflicted with what I had said:
2 No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
Offline
I actually interpreted that as confirming your and my usage of the single-underscore prefix (with the exception of my _PRINT macro, because it begins with an underscore and a capital letter).
Right, that makes sense in the plain-English reading of the second point, but that meaning of "reserved" can't be applied to the other uses of the word "reserved" under 7.1.3. That is, if I interpret "identifiers [...] are always reserved for any use" to mean "you may not use these identifiers for anything", then I must also interpret "identifiers that begin with an underscore are always reserved for use as blah blah blah" as "you may not use these identifiers for blah blah blah". At least, I spent a good half an hour studying that section and that's the best I could come up with.
I've seen others use single-underscore prefixes in the same way I do, though, so perhaps this is not the intended meaning. I wonder if it's phrased differently in C89 or C11.
Offline