Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C naming conventions

287 views
Skip to first unread message

Thiago Adams

unread,
Aug 27, 2022, 7:06:12 PM8/27/22
to
I am searching for C naming conventions.
For instance, how to name structs, function, global variables...

Any link? What are the "classic ones? "

I think one sample is "Win32" API

anti...@math.uni.wroc.pl

unread,
Aug 27, 2022, 7:43:04 PM8/27/22
to
Conventions changed with tools. Early ones has to cope
with case insentitive linkers which allowed only 6
significant characters in name. So you got elaborate
schemes to put some info into name, but for bigger
systems after some evolution people ended with
complete nonsense. Of course, people familiar
with system memorised frequently used names,
but it was hard for newcomers.

I normaly use rather long names with parts separated
by underscores. I am trying to use sensible names
without makeing them too long. For example, in
small program I have:

#define MAX_NAME_LENGTH 30
#define MAX_NAMES 500
typedef struct {char name[MAX_NAME_LENGTH]; void * val;} symtab_pos;

As you can see for macro constants I prefer uppercase, normal
names almost exclusively lowercase. In bigger program anything
global would get prefix corresonding to module/sybsustem.
For local variables I use i, j, x and similar.

There is CamelCase camp. Concering Win32 API they have part
under influence of hungarian notation, which basically tries
to put type information in few characters and use them as
part of name. This makes some sense for baroque interfaces
like Win API, but I would avoid this for my code.

--
Waldek Hebisch

Thiago Adams

unread,
Aug 28, 2022, 11:42:40 PM8/28/22
to
On Saturday, August 27, 2022 at 8:43:04 PM UTC-3, anti...@math.uni.wroc.pl wrote:
> Thiago Adams <thiago...@gmail.com> wrote:
> > I am searching for C naming conventions.
> > For instance, how to name structs, function, global variables...
> >
> > Any link? What are the "classic ones? "
> >
> > I think one sample is "Win32" API
> Conventions changed with tools. Early ones has to cope
> with case insentitive linkers which allowed only 6
> significant characters in name. So you got elaborate
> schemes to put some info into name, but for bigger
> systems after some evolution people ended with
> complete nonsense. Of course, people familiar
> with system memorised frequently used names,
> but it was hard for newcomers.
>
Interesting.

> I normaly use rather long names with parts separated
> by underscores.

One advantage I see in camelCase or pascal Case is that using underscore
can separate two blocks one being the "subject "

Window_SetText()
Window_SetPos()

compare with
window_set_pos()

>I am trying to use sensible names
> without makeing them too long. For example, in
> small program I have:
>
> #define MAX_NAME_LENGTH 30
> #define MAX_NAMES 500
> typedef struct {char name[MAX_NAME_LENGTH]; void * val;} symtab_pos;
>
> As you can see for macro constants I prefer uppercase, normal

Upper case for macros are good to put then in a separate "namespace".
and the bigger names are useful anyway because they are global



Thiago Adams

unread,
Aug 29, 2022, 12:02:12 PM8/29/22
to

Opus

unread,
Aug 29, 2022, 2:07:10 PM8/29/22
to
That's interesting. Turns out there's a lot in there that closely
matches my own style. Except for the naming convention! For which I do
favor CamelCase for all identifiers, and as the Window_SetText() example
you gave, I also use underscores to indicate hierarchical structure.

And for types, I suffix them with '_t' as the C standard does.


Ben Bacarisse

unread,
Aug 29, 2022, 4:25:15 PM8/29/22
to
Blimey! Not an impressive work by any means. Full of errors (ok,
probably minor ones, but even so...). Uses K&R syntax in places. In
one place the examples have been updated to C90, but the text still
talks about K&R syntax.

Oh, I've now read some more and it's truly dreadful. I'd list some of
the issues but there are so many it's just better to forget the whole
thing.

--
Ben.

Thiago Adams

unread,
Aug 29, 2022, 9:15:45 PM8/29/22
to
One "problem" with camel case is that c functions like fopen etc..
does not follow the rule resulting in a mixed style.


Thiago Adams

unread,
Aug 29, 2022, 9:46:28 PM8/29/22
to
On Monday, August 29, 2022 at 10:15:45 PM UTC-3, Thiago Adams wrote:
..> One "problem" with camel case is that c functions like fopen etc..
> does not follow the rule resulting in a mixed style.

if we try to follow the existing c style..then we have more than one style

error constants

enum {

thrd_success = /* unspecified */,
thrd_nomem = /* unspecified */,
thrd_timedout = /* unspecified */,
thrd_busy = /* unspecified */,
thrd_error = /* unspecified */
};

other constants
enum memory_order {

memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
};
macros
#define LC_ALL /*implementation defined*/
#define LC_COLLATE /*implementation defined*/
..

and some posix errors are UPPER

typedef is sometimes upper

typedef /* unspecified */ FILE;

or
thrd_t implementation-defined complete object type identifying a thread

functions

int thrd_create( thrd_t *thr, thrd_start_t func, void *arg );

or
void atomic_signal_fence( memory_order order );

or

strcmp
int isgreater(real-floating x, real-floating y);
int isgreaterequal(real-floating x, real-floating y);

bool ckd_mul(type1 *result, type2 a, type3 b


macros sometimes are lowecase

stderr, offsetof, errno
int isless(real-floating x, real-floating y);




luser droog

unread,
Aug 29, 2022, 10:13:04 PM8/29/22
to
On Sunday, August 28, 2022 at 10:42:40 PM UTC-5, Thiago Adams wrote:
> On Saturday, August 27, 2022 at 8:43:04 PM UTC-3, anti...@math.uni.wroc.pl wrote:
> > I normaly use rather long names with parts separated
> > by underscores.
> One advantage I see in camelCase or pascal Case is that using underscore
> can separate two blocks one being the "subject "
>
> Window_SetText()
> Window_SetPos()
>
> compare with
> window_set_pos()

Upon first reading this, I thought "ooh, that's neat." Then searching my memory for
where such a thing might be needed I remembered that I've already done this before.

In my PostScript interpreter, there's a struct Xpost_Memory_File which describes
the whole memory space in which the language objects live. But there's also a
struct Xpost_MemoryFile which is a subclass of struct Xpost_File presenting
a FILE interface to a block of memory.

And reflecting upon that, it may indeed be "neat" but it's also goddoffal. I wish I had
come up with a better way to distinguish these very different things than the
presence or absence of a single underscore. It's still the same words. When I
verbalize the code it in my head while reading it, the underscores disappear.
You can kinda sound the words closer to together to reflect the difference, but ...
there's got to be a better way. There just has to. In my opinion. FWIW.

Opus

unread,
Aug 29, 2022, 11:22:22 PM8/29/22
to
I know! But even the C std uses a mixed style. So...

I find it best to pick what works for you and be consistent about what
*you* have an influence on, and just accept (or reject if you can) the
rest. If anything here, having a clearly different style immediately
shows what part of the code is yours and what isn't.

Inconsistency within a development team is a problem and then that's the
job of managers to deal with it. But some inconsistency between your
style and whatever styles have piled up in the C std over 33 years (or
50 if you count C's legacy since its inception), I'm not too worried
about it. Pick your battles. :)




Thiago Adams

unread,
Aug 30, 2022, 1:54:12 PM8/30/22
to
On Monday, August 29, 2022 at 11:13:04 PM UTC-3, luser droog wrote:
> On Sunday, August 28, 2022 at 10:42:40 PM UTC-5, Thiago Adams wrote:
> > On Saturday, August 27, 2022 at 8:43:04 PM UTC-3, anti...@math.uni.wroc.pl wrote:
> > > I normaly use rather long names with parts separated
> > > by underscores.
> > One advantage I see in camelCase or pascal Case is that using underscore
> > can separate two blocks one being the "subject "
> >
> > Window_SetText()
> > Window_SetPos()
> >
> > compare with
> > window_set_pos()
> Upon first reading this, I thought "ooh, that's neat." Then searching my memory for
> where such a thing might be needed I remembered that I've already done this before.
>

These samples are from Win23 GDI. "Pen" is a object it has a handle.

CreatePen
CreatePenIndirect
ExtCreatePen
SetDCPenColor

The word "Pen" is present in all function but not as prefix like:

Pen_Create
Pen_CreateIndirect
Pen_ExtCreate
Pen_SetDCColor

Does anyone have a preference?
The advange of CreatePen is no need for "_"
and the advantage of Pen_Create is auto complete in modern IDEs.

Opus

unread,
Aug 30, 2022, 2:21:44 PM8/30/22
to
I personally use underscores and prefixes to indicate "hierarchy". I
will thus tend to prefer the latter version, although in my code, it
would probably have additional prefixes if the "Pen" functions are part
of some "module" or library. So that would more look like (for instance):

GDI_Pen_Create

Yes, that's a lot of underscores. Yes, that's partly because C doesn't
have modules, classes or even separate namespaces. But I don't mind.
Auto-complete works in all decent text editors I have used. They don't
even have to be ultra-modern or trendy.



Anton Shepelev

unread,
Aug 30, 2022, 6:38:29 PM8/30/22
to
Thiago Adams:

> I am searching for C naming conventions. For instance,
> how to name structs, function, global variables...

I like the minimalist beauty of lowercase indentifers with
understores, with constants and macros in uppercase. If
need be, I will prefix globals with g_ and function-types
with f_. PascalCase is somehow counter-C, and combining it
with Under_Scores looks ugly. In C#, I sometimes use
BQ_AddToEnd(), but my prefix is stritly a short acronym
denoting a sub-module (Binary Queue) withing a module
(static class). But then, PascalCase is native to C#.

> Any link?

The one know one else will give you:

http://z505.com/cgi-bin/qkcont/qkcont.cgi?p=Underscores Discussion

It disagrees with my approach, but is worth reading at least
for the fun of it.

> What are the "classic ones?"

The one minimalist one, see K&R.

> I think one sample is "Win32" API

I hate it for absudly long funtion names and for Hungarian
notaiton.

--
() ascii ribbon campaign -- against html e-mail
/\ http://preview.tinyurl.com/qcy6mjc [archived]

luser droog

unread,
Aug 30, 2022, 10:36:22 PM8/30/22
to
I dug into this area 10 years or so, even reading the paper by Simonyi, but
IMO the best result here is "Apps Hungarian" where you pretty much don't
do it at all like everybody else has continued to do it. The Win32 is an
appropriately horrible example that illustrates why "Systems Hungarian"
is just awful.

I'll describe the conventions I've applied in my parser combinators which
I'm reasonably happy with. Other may disagree. And this may or may not
fit any rigorous definition for Apps Hungarian that may have arisen in the
interim from the time I actually looked at this.

I use plain old lowercase words for type names, and the Capitalized
version of the same word for the associated constructor for that type.
The all-caps version of the same word is used in the tag field for the
structs for dynamic type dispatching.

Function names (in this "functional style" code body) ought to reflect
what the result value is, and so tend to be more adjectives and past tense
verbs.

A function that "does something" rather than produce something should
be a verb in the imperative mood. A function producing a function object
that "does something" should be the same verb but in the present tense
indicative mood.

Eg.

static object
fail( object errormsg, list input );

is a parsing function which always fails when called.

parser fails( list errormsg );

is a constructor which produces the function object which couples
the `fail` parsing function and it's saved argument.

An example function names that describe the result rather that what
it's doing:

list ucs4_from_utf8( list o );
list utf8_from_ucs4( list o );

They're both doing stream conversion, but the function name would
just be cluttered if those words (or worse, abbreviations) crept in there.

Thiago Adams

unread,
Aug 31, 2022, 7:37:32 AM8/31/22
to
I was considering prefix when I had this problem.

struct X {
char * name;
char email[100];
};

if (strcmp(pX->name, "a") == ) {}
if (strcmp(pX->email, "a") == ) {}

Both compiles and have the same syntax. Bust just
one of then can "explode" that is strcmp(pX->name, "a").

Ben Bacarisse

unread,
Aug 31, 2022, 10:31:03 AM8/31/22
to
Thiago Adams <thiago...@gmail.com> writes:

> I was considering prefix when I had this problem.
>
> struct X {
> char * name;
> char email[100];
> };
>
> if (strcmp(pX->name, "a") == ) {}
> if (strcmp(pX->email, "a") == ) {}
>
> Both compiles and have the same syntax. Bust just
> one of then can "explode" that is strcmp(pX->name, "a").

What do you mean "explode"? (BTW, I'm assuming struct X *pX;)

--
Ben.

Lew Pitcher

unread,
Aug 31, 2022, 10:50:41 AM8/31/22
to
I won't see Thiago's reply.

Consider
struct X liveX = {NULL,"a"};
struct X *pX = &liveX;

strcmp(pX->name,"a");

What happens when strcmp() dereferences pX->name and tries to
compare the string at NULL to the string "a" ?

--
Lew Pitcher
"In Skills, We Trust"

Scott Lurndal

unread,
Aug 31, 2022, 10:57:46 AM8/31/22
to
The same thing that happens when strcmp dereferences pX->email when
pX == NULL.

Thiago Adams

unread,
Aug 31, 2022, 11:36:24 AM8/31/22
to
Yes, this is my point.

#include <string.h>

struct X {
char * name;
char email[100];
};

void F(struct X* p) {
if (strcmp(p->name, "name") == 0 ||
strcmp(p->email, "email") == 0)
{}
}
int main(){
struct X x = {0};
F(&x);
}


Thiago Adams

unread,
Aug 31, 2022, 11:44:49 AM8/31/22
to
On Wednesday, August 31, 2022 at 11:57:46 AM UTC-3, Scott Lurndal wrote:
...
> >What happens when strcmp() dereferences pX->name and tries to
> >compare the string at NULL to the string "a" ?
> The same thing that happens when strcmp dereferences pX->email when
> pX == NULL.

In this sample:

strcmp(pX->name,"a");

We can see pX is a pointer because of "->", but we cannot see
if name is a pointer or array. This makes a lot of difference
considering that strcmp don't accept null pointers.


Ben Bacarisse

unread,
Aug 31, 2022, 12:51:07 PM8/31/22
to
Is this what TA meant? Does he want the naming convention to somew how
prevent this? Thanks for suggesting a meaning, but I am left with more
questions...

--
Ben.

Ben Bacarisse

unread,
Aug 31, 2022, 12:54:25 PM8/31/22
to
OK. Not an easy guess for me because email can also "explode" if it's
not null terminated (technically even when compared to "a"). The
initial value of both members determines what operations are valid on
them.

--
Ben.

Lew Pitcher

unread,
Aug 31, 2022, 1:14:45 PM8/31/22
to
I get the impression that TA is looking for someone to codify
"Systems Hungarian" notation[1] or something similar as either a C
language standard or a "shop" requirement for C programming.

In that case, the example would change to something like:
struct X {
char * pszName; char rgchszEmail[100];
};

struct X structX = {NULL,"a"};
struct X *pX = &structX;

strcmp(pX->pszName,"a");
strcmp(pX->rgchszEmail,"a");

(Forgive me if I've mangled some of these identifiers. I abhor
Hungarian notation, and do not practice it myself.)

[1] https://en.wikipedia.org/wiki/Hungarian_notation#Systems_Hungarian_vs._Apps_Hungarian

Thiago Adams

unread,
Aug 31, 2022, 1:21:45 PM8/31/22
to
no..just asking if in this situation a naming convention for "pointer"
or "pointer to string" would be a advantage.
I am not using prefixes but after to see this situation in my code
I have considered to use a prefix.

Kent Dickey

unread,
Sep 5, 2022, 2:00:10 PM9/5/22
to
In article <3e090bd4-4274-467b...@googlegroups.com>,
Most people know they need some convention. Most people hate any particular
convention. Pick a convention for a project, stick to it, change conventions
for a new project. Go ahead and let sub-projects (or libraries to the
project) try new conventions, as long as they are roughly compatible, or are
so different as to be obvious. Don't mix conventions within a file ever.

I'll summarize my rules:
All structs must be typedef'ed and the typedef name is an initial capital.
All structs are created by STRUCT(Sample_structure) where STRUCT is:
#define STRUCT(a) typedef struct a ## _st a; struct a ## _st
The word "struct" and "typedef" should never appear in any code, other than
the STRUCT #define.
This means there is no typedef char **Ptr_str; nonsense to decode.
If you see "struct", it means this is for a library/OS call.
Global variables start with an initial cap (like typedef names), or g_.
Make a distinction between them only if needed--I have some global
variables which are special, so they get the initial capital, all the
rest are g_.
Structure fields follow the local variable rules.
Local variable and function names are all lower case.
All names use _ and not CamelCase. I think this works best when you use
libs which are CamelCase, since it's easy to tell when you are calling
outside your code. If this hurts your eyes, then get new glasses.
All #defines are all-caps. No other identifier can be all-cap.
"#define NUM_THINGS 5" is fine. #define FUNC_THIS(a) must have
"(a)" on the right hand side in all instances. Anything more complex
than a single number or variable must wrap the definition with ().
Enums are like structures and are Initial_capital for the type. It's
easy to tell these apart from structs.
I'm ambivalent on enums vs #defines, but enums of arbitrary things
should start at 1 so that 0 is always an error value.
Function names include the file name (or a short form of it) as a prefix.
So serial.c would have serial_init(), serial_out_char(), etc.
But windows_serial.c could be wser_init(), etc, just to shorten things.
All functions in one file must use the same prefix.
I have a simple hungarian notation: 64-bit variables have a 'd' in the name
that is meaningful: "dval", "init_dtmp". "do_this" is not 64-bit.
Pointers have "ptr" in the name somewhere, often at the end (but
"userptr2" is fine), except char * pointers should use "str" in the
name somewhere. Non pointers variables never have str or ptr
in the name. For your app, try to use consistent names: Don't let
"val" be unsigned sometimes and signed other times. Pick a convention
and stick with it. I like val to be unsigned, and tmp to be signed.
So last_val is unsigned, and prev_tmp is an int.
Loop counters can be i,j,k, but all other variables should briefly
describe what it is. "tmp" or "val" are only ok for brief usage.
Declaring variables never initializes them, except for global variables.
Use -Wall -Werror to ensure everything is initialized. This is so
the declarations can be ignored when reading code since they
provide no new information.
When passing around an array, always use &array[0] notation to indicate
"array" is an array and not a pointer.

The advantage of this is you can begin reading any file and have an idea
what functions it's calling and even what work it's doing, without
having to constantly look at header files or variable declarations. And
the light Hungarian notation means you don't have to read declarations,
so I pack them tightly with many variables per line just to be done with
them. Variables are declared in order by type: arrays, then pointers,
then ints, and by size within each type. It's not legal to mix pointers
and ints in declarations, so you cannot do: "int a, *ptr1, b, c[100];"

I use special typedefs for unsigned types: byte, word16, word32, and dword64
of the obvious sizes. These are the only typedefs that are not structures
and are not capitalized. I'm less likely to mix them up since byte,
word32, and dword64 are all different lengths and multiple keystrokes
apart: word64 and dword32 are not valid. It's hard to tell uint32_t
from uint64_t, they tend to blend together to my eyes in large
structures, and getting them mixed up is a very annoying bug.

Kent

Anton Shepelev

unread,
Sep 5, 2022, 4:32:03 PM9/5/22
to
Thiago Adams:

> I was considering prefix when I had this problem.
>
> struct X {
> char * name;
> char email[100];
> };
>
> if (strcmp(pX->name, "a") == ) {}
> if (strcmp(pX->email, "a") == ) {}
>
> Both compiles and have the same syntax. Bust just
> one of then can "explode" that is strcmp(pX->name, "a").

There are other ways to deal with devilish details than
naming:

1. make sure that both .name and .email are proper C
strings, e.g. by way of a single constructor function
or dedicated `setter' functions,
2. implement explosive operations on X as reusable
functions,
3. work with X as with an opaque type,
4. roll your own strcmp that handles NULL.
5. generally and when appropriate, follow Robert Martin's
advice to avoid "primitive obsession".

Bart

unread,
Sep 5, 2022, 4:44:55 PM9/5/22
to
Both can 'explode', for example when .email is not properly initialised
and can be full of non-zero-terminated garbage.

If you mean that, even if an instance of struct X is zeroed, then .email
is in a safe state but .name can be NULL, then I don't know how naming
will help much.

I usually assume such strings can be NULL anyway, as can .email be if at
some point you decide to change how it's implemented, but you don't
really want to go about changing all the names.

Thiago Adams

unread,
Sep 5, 2022, 9:00:27 PM9/5/22
to
I am considering a valid estate that is - empty string.
But empty string have different representation, unless we allocate "\0"
for the pointer version.
So basically is not about invalid/wrong states..is about valid states
having different semantics that can be dangerous.






Blue-Maned_Hawk

unread,
Sep 6, 2022, 2:16:50 AM9/6/22
to
On 8/27/22 19:06, Thiago Adams wrote:
> I am searching for C naming conventions.
> For instance, how to name structs, function, global variables...
>
> Any link? What are the "classic ones? "
>
> I think one sample is "Win32" API

I'll begin by saying that I AM NOT AN EXPERT IN C PROGRAMMING, NOR AM I
PARTICULARLY GOOD AT GIVING ADVICE. With that out of the way…

If you are contributing to someone else's project, _**always**_ use the
style of the surrounding code. This is the polite thing to do, and it
means your code won't look out of place. Maybe you could politely
discuss changing the project's code style, but until and unless that
change happens, just use what's already being used.

You should write macros in SCREAMING_CASE. Macros are unsanitary in C,
so screaming their names helps to indicate that they can seriously mess
shit up.

Names should be useful. Don't name something `fkKFHsna`, because other
people (including your future self!) will have difficulty trying to
figure out what it means. On the other hand, naming a `for` loop's
iterator `i` or using acronyms like `tmp` is probably okay.

Keep consistency with other names—for example, if alternative
subroutines that take a `va_list` instead of a `...` are prefixed with a
"v", don't name yours `original_funcname_with_va_list` or something.

Beyond that…eh, i don't fuckin' know. Most of this is subjective and
highly context dependent, so there's not really a "perfect" system of
names, and trying to impose one would be pointless. I have some
personal opinions on the whole matter (never use typedefs, be chaotic,
dollar signs as hierarchy position separators…), but i don't really feel
like listing all of them out here.
​
--
/blu.mɛin.dʰak/ | shortens to "Hawk" | he/him/his/himself/Mr.
bluemanedhawk.github.io
I think my Usenet provider stores their passwords in plain text. If i'm
acting suspiciously, chances are that that backfired on them.


Blue-Maned_Hawk

unread,
Sep 6, 2022, 2:21:39 AM9/6/22
to
On 8/29/22 21:46, Thiago Adams wrote:
> On Monday, August 29, 2022 at 10:15:45 PM UTC-3, Thiago Adams wrote:
> ..> One "problem" with camel case is that c functions like fopen etc..
>> does not follow the rule resulting in a mixed style.
>
> if we try to follow the existing c style..then we have more than one style
> > [snip]
>
> typedef is sometimes upper
>
> typedef /* unspecified */ FILE;

I believe i saw somewhere that `FILE` and `DIR` in particular came about
as capitalized because, in the old Unix systems that the C standard and
POSIX are based upon, they were defined as macros instead of typedefs
(for some reason?), and standard practice was that macros are in
screaming case. Unfortunately, i don't remember where i saw this, so i
don't have any sort of citation.

Ben Bacarisse

unread,
Sep 6, 2022, 5:52:20 AM9/6/22
to
Blue-Maned_Hawk <bluema...@example.invalid> writes:

> On 8/29/22 21:46, Thiago Adams wrote:
>> On Monday, August 29, 2022 at 10:15:45 PM UTC-3, Thiago Adams wrote:
>> ..> One "problem" with camel case is that c functions like fopen etc..
>>> does not follow the rule resulting in a mixed style.
>> if we try to follow the existing c style..then we have more than one style
>> > [snip]
>>
>> typedef is sometimes upper
>> typedef /* unspecified */ FILE;
>
> I believe i saw somewhere that `FILE` and `DIR` in particular came
> about as capitalized because, in the old Unix systems that the C
> standard and POSIX are based upon, they were defined as macros instead
> of typedefs (for some reason?), and standard practice was that macros
> are in screaming case.

C was developed over the course of a few years as a working language and
FILE was needed and defined before the language had typedef.

--
Ben.

Keith Thompson

unread,
Sep 6, 2022, 2:03:56 PM9/6/22
to
Blue-Maned_Hawk <bluema...@example.invalid> writes:
> On 8/29/22 21:46, Thiago Adams wrote:
>> On Monday, August 29, 2022 at 10:15:45 PM UTC-3, Thiago Adams wrote:
>> ..> One "problem" with camel case is that c functions like fopen etc..
>>> does not follow the rule resulting in a mixed style.
>> if we try to follow the existing c style..then we have more than one
>> style
>> > [snip]
>>
>> typedef is sometimes upper
>> typedef /* unspecified */ FILE;
>
> I believe i saw somewhere that `FILE` and `DIR` in particular came
> about as capitalized because, in the old Unix systems that the C
> standard and POSIX are based upon, they were defined as macros instead
> of typedefs (for some reason?), and standard practice was that macros
> are in screaming case. Unfortunately, i don't remember where i saw
> this, so i don't have any sort of citation.

It's possible that FILE was invented before typedef was added to the
language, though I can't verify that.

typedef was a relatively late addition. It's in K&R1 (1978), but isn't
mentioned in the 1975 C reference manual. The 1975 manual doesn't
mention FILE, but it does mention the "C library", which included at
least printf() and putchar().

https://www.bell-labs.com/usr/dmr/www/cman.pdf

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

Thiago Adams

unread,
Sep 11, 2022, 12:22:31 PM9/11/22
to
On Wednesday, August 31, 2022 at 8:37:32 AM UTC-3, Thiago Adams wrote:
[...]
> I was considering prefix when I had this problem.
>
> struct X {
> char * name;
> char email[100];
> };
>
> if (strcmp(pX->name, "a") == ) {}
> if (strcmp(pX->email, "a") == ) {}
>
> Both compiles and have the same syntax. Bust just
> one of then can "explode" that is strcmp(pX->name, "a").


I was removing the prefix 'p' for pointers in my code, especially for structs
because generally they are used with "->" so it is clear that is a pointer.
Then I found

struct macro* macro = calloc(1, sizeof * macro);

Here the prefix "p" for "macro" can be useful because "->" is
not present. The result is completely different.

For this particular case we can do
struct macro* macro = calloc(1, sizeof (struct macro));

Another item I found difficult is the prefix "b" for bool.
When "is" or "has" can be used it is easy.

bool is_enabled;
bool has_something;

the problem is when it is like a verb.

void F(struct Something * s, bool bAddHeader){}
void F(struct Something * s, bool bEnableCheck){}

What names do you use in this case? (for those don't use prefix b)
Just enable_check and add_header ?

Bonita Montero

unread,
Sep 11, 2022, 1:31:31 PM9/11/22
to
Use Java's kind of "camelCase" !

Ben Bacarisse

unread,
Sep 11, 2022, 3:33:32 PM9/11/22
to
Thiago Adams <thiago...@gmail.com> writes:

> On Wednesday, August 31, 2022 at 8:37:32 AM UTC-3, Thiago Adams wrote:
> [...]
>> I was considering prefix when I had this problem.
>>
>> struct X {
>> char * name;
>> char email[100];
>> };
>>
>> if (strcmp(pX->name, "a") == ) {}
>> if (strcmp(pX->email, "a") == ) {}
>>
>> Both compiles and have the same syntax. Bust just
>> one of then can "explode" that is strcmp(pX->name, "a").
>
>
> I was removing the prefix 'p' for pointers in my code, especially for structs
> because generally they are used with "->" so it is clear that is a pointer.
> Then I found
>
> struct macro* macro = calloc(1, sizeof * macro);
>
> Here the prefix "p" for "macro" can be useful because "->" is
> not present. The result is completely different.

I don't understand the last sentence, but I also don't understand why
you think it's not clear that macro is a pointer from that line.

My own opinion is that the distinction between an object and a pointer
to an object is so important it /should/ be part of the name. I don't
like unreadable prefixes, but I often write things line macro_ptr.

I also prefer to reflect the syntax (and meaning) in the layout so I'd
tick the * to the name. I /try/ not to react when I see int* p, but
it's a hard internal struggle. I would never want to write it, any more
than I would want to write a+2 * b instead of a + 2*b.

> For this particular case we can do
> struct macro* macro = calloc(1, sizeof (struct macro));

How does that make any difference? I'm obviously missing something here.

> Another item I found difficult is the prefix "b" for bool.
> When "is" or "has" can be used it is easy.
>
> bool is_enabled;
> bool has_something;
>
> the problem is when it is like a verb.
>
> void F(struct Something * s, bool bAddHeader){}
> void F(struct Something * s, bool bEnableCheck){}

As far as possible, I try to avoid this sort of thing ("pass data to
functions, not control") but when cornered, I'd just use the verb as you
suggest here:

> What names do you use in this case? (for those don't use prefix b)
> Just enable_check and add_header?

What else could a Boolean verb mean other than to do the thing or not do
it? The trouble is, though, that in languages without named arguments
in function calls, the meaning of argument (rather than the parameter)
is lost to the reader:

F(struct_ptr, true);
F(struct_ptr, size < max_size);

--
Ben.

Thiago Adams

unread,
Sep 11, 2022, 4:18:12 PM9/11/22
to
On Sunday, September 11, 2022 at 4:33:32 PM UTC-3, Ben Bacarisse wrote:
> Thiago Adams <thiago...@gmail.com> writes:
>
> > On Wednesday, August 31, 2022 at 8:37:32 AM UTC-3, Thiago Adams wrote:
> > [...]
> >> I was considering prefix when I had this problem.
> >>
> >> struct X {
> >> char * name;
> >> char email[100];
> >> };
> >>
> >> if (strcmp(pX->name, "a") == ) {}
> >> if (strcmp(pX->email, "a") == ) {}
> >>
> >> Both compiles and have the same syntax. Bust just
> >> one of then can "explode" that is strcmp(pX->name, "a").
> >
> >
> > I was removing the prefix 'p' for pointers in my code, especially for structs
> > because generally they are used with "->" so it is clear that is a pointer.
> > Then I found
> >
> > struct macro* macro = calloc(1, sizeof * macro);
> >
> > Here the prefix "p" for "macro" can be useful because "->" is
> > not present. The result is completely different.
> I don't understand the last sentence, but I also don't understand why
> you think it's not clear that macro is a pointer from that line.

I was worried about a mistake like

macro = calloc(1, sizeof macro);

when trying to write
macro = calloc(1, sizeof * macro);

The prefix "p" would have the advantage of making it
a little more explicit.

macro = calloc(1, sizeof pmacro); //Visually.. What? sizeof of pointer ?

(But I am still removing prefix from my code and I want do see
what happens)

The correct code has the "* " in front of the macro, so the correct
code has the information we want the size of the object not the pointer.

luser droog

unread,
Sep 12, 2022, 12:17:02 AM9/12/22
to
On Sunday, September 11, 2022 at 2:33:32 PM UTC-5, Ben Bacarisse wrote:
> Thiago Adams <thiago...@gmail.com> writes:
>
> > On Wednesday, August 31, 2022 at 8:37:32 AM UTC-3, Thiago Adams wrote:
> > [...]
> >> I was considering prefix when I had this problem.
> >>
[snip]
> > Another item I found difficult is the prefix "b" for bool.
> > When "is" or "has" can be used it is easy.
> >
> > bool is_enabled;
> > bool has_something;
> >
> > the problem is when it is like a verb.
> >
> > void F(struct Something * s, bool bAddHeader){}
> > void F(struct Something * s, bool bEnableCheck){}
> As far as possible, I try to avoid this sort of thing ("pass data to
> functions, not control") but when cornered, I'd just use the verb as you
> suggest here:
> > What names do you use in this case? (for those don't use prefix b)
> > Just enable_check and add_header?
> What else could a Boolean verb mean other than to do the thing or not do
> it? The trouble is, though, that in languages without named arguments
> in function calls, the meaning of argument (rather than the parameter)
> is lost to the reader:
>
> F(struct_ptr, true);
> F(struct_ptr, size < max_size);
>

For this problem, it can be nice to use a custom enum even though it's
logically a boolean in disguise.

enum { DO_NOT_ADD_HEADER, ADD_HEADER };
enum { NO_ENABLE_CHECK, ENABLE_CHECK };

Chris M. Thomasson

unread,
Sep 12, 2022, 3:46:01 AM9/12/22
to
On 9/11/2022 10:31 AM, Bonita Montero wrote:
> Use Java's kind of "camelCase" !
>

For C, usually a:

author_namespace_lib_function

setup.

ct_cairo_2dplot_project

ct_fractal_ttr_compute

ct_cairo_2dplot_project would typically work on a ct_cairo_2dplot struct:

struct ct_cairo_2dplot { ... };



ct_cairo_2dplot_project(struct ct_cairo_2dplot const*, ...)




Ben Bacarisse

unread,
Sep 12, 2022, 6:51:29 AM9/12/22
to
My preference is to have only enum { ENABLE_CHECK = true }; (or = 1) and
use !ENABLE_CHECK. The ! gets a bit hidden but it can help to make
clear that this is Boolean in disguise.

But using an enum gets ugly and long-winded in the second example,
unless you are prepared to write

F(struct_ptr, ENABLE_CHECK * (size < max_size));

which would give most people here the heebee-jeebies.

--
Ben.

Tim Rentsch

unread,
Sep 12, 2022, 10:12:18 AM9/12/22
to
ke...@provalid.com (Kent Dickey) writes:

> In article <3e090bd4-4274-467b...@googlegroups.com>,
> Thiago Adams <thiago...@gmail.com> wrote:
>
>> I am searching for C naming conventions.
>> For instance, how to name structs, function, global variables...
>>
>> Any link? What are the "classic ones? "
>>
>> I think one sample is "Win32" API
>
> Most people know they need some convention. Most people hate any particular
> convention. Pick a convention for a project, stick to it, change conventions
> for a new project. Go ahead and let sub-projects (or libraries to the
> project) try new conventions, as long as they are roughly compatible, or are
> so different as to be obvious. Don't mix conventions within a file ever.
>
> I'll summarize my rules:

An interesting set of ideas. Comments are offered in some select
cases.


> All structs must be typedef'ed and the typedef name is an initial capital.

I try to follow the rule that all (developer-chosen) type names
start with a capital letter, and no other names do. (Preprocesor
symbols are treated separately.)


> All structs are created by STRUCT(Sample_structure) where STRUCT is:
> #define STRUCT(a) typedef struct a ## _st a; struct a ## _st

It is a little bit safer if STRUCT(a) were defined

#define STRUCT(a) \
struct a ## _st; typedef struct a ## _st a; struct a ## _st

The reasons are somewhat esoteric. But since the leading
declaration is hidden inside a macro, it seems better to use the
safer form.


> The word "struct" and "typedef" should never appear in any code, other than
> the STRUCT #define.
> This means there is no typedef char **Ptr_str; nonsense to decode.
> If you see "struct", it means this is for a library/OS call.

I have a different view regarding other typedefs. However I
think I understand your motivations, and won't argue the point.


> Structure fields follow the local variable rules.

My instinctive reaction is that the rules for struct members
should be more stringent than the rules for local variables.
That said, this rule is a good baseline.


> Local variable and function names are all lower case.

Of course (with some allowances for acronyms, which might appear
as all-capitals "words" within a larger all lower case context).


> All names use _ and not CamelCase.

Generally using underscores is better than either CamelCase or
camelCase, for ergonomic reasons. An exception is type names,
where for example TreeNode arguably reads better than Tree_node.
(The type-name exception tacitly assumes that type names are
limited to at most four or five words; more than that runs
into readability problems.)


> All #defines are all-caps. No other identifier can be all-cap.
> "#define NUM_THINGS 5" is fine. #define FUNC_THIS(a) must have
> "(a)" on the right hand side in all instances. Anything more complex
> than a single number or variable must wrap the definition with ().

Generally yes; there may be exceptions in some special cases.


> Function names include the file name (or a short form of it) as a prefix.
> So serial.c would have serial_init(), serial_out_char(), etc.
> But windows_serial.c could be wser_init(), etc, just to shorten things.
> All functions in one file must use the same prefix.

Having a prefix seems reasonable. Insisting that the prefix be
tied to the file name seems excessive.


> I have a simple hungarian notation: 64-bit variables have a 'd' in the name
> that is meaningful: "dval", "init_dtmp". "do_this" is not 64-bit.
> Pointers have "ptr" in the name somewhere, often at the end (but
> "userptr2" is fine), except char * pointers should use "str" in the
> name somewhere. Non pointers variables never have str or ptr
> in the name. For your app, try to use consistent names: Don't let
> "val" be unsigned sometimes and signed other times. Pick a convention
> and stick with it. I like val to be unsigned, and tmp to be signed.
> So last_val is unsigned, and prev_tmp is an int.
> Loop counters can be i,j,k, but all other variables should briefly
> describe what it is. "tmp" or "val" are only ok for brief usage.

IMO encoding the type of a variable in its name is just wrong.
If a function has so many names that it's difficult to remember
what types go with which names then the function is too big. For
global names or struct members, if knowing the types is any
significant burden then any uses of those names should be
encapsulated, reducing their surface area.


> Declaring variables never initializes them, except for global variables.
> Use -Wall -Werror to ensure everything is initialized. This is so
> the declarations can be ignored when reading code since they
> provide no new information.

Interesting argument. I may try adopting this rule for a while.


> When passing around an array, always use &array[0] notation to indicate
> "array" is an array and not a pointer.

I follow a different rule: 'array' by itself means the whole
array, '&array[0]' means just the one element is referenced.


> The advantage of this is you can begin reading any file and have an idea
> what functions it's calling and even what work it's doing, without
> having to constantly look at header files or variable declarations. And
> the light Hungarian notation means you don't have to read declarations,
> so I pack them tightly with many variables per line just to be done with
> them. Variables are declared in order by type: arrays, then pointers,
> then ints, and by size within each type. It's not legal to mix pointers
> and ints in declarations, so you cannot do: "int a, *ptr1, b, c[100];"

My sense is that these motivations assume a style of coding that
is different from my usual style(s). And hence, consequently,
work better in some coding/development styles than others. It
would be interesting to explore that question further at some
point.


> I use special typedefs for unsigned types: byte, word16, word32, and dword64
> of the obvious sizes. These are the only typedefs that are not structures
> and are not capitalized. I'm less likely to mix them up since byte,
> word32, and dword64 are all different lengths and multiple keystrokes
> apart: word64 and dword32 are not valid. It's hard to tell uint32_t
> from uint64_t, they tend to blend together to my eyes in large
> structures, and getting them mixed up is a very annoying bug.

IMO using type names like word32 or dword64 (or uint32_t or
uint64_t) in open code is generally a bad idea. So here again I
expect that the efficacy of these particular rules depends on
program style on a larger scale.

Kent Dickey

unread,
Sep 12, 2022, 11:54:01 PM9/12/22
to
In article <86edwgp...@linuxsc.com>,
Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
>ke...@provalid.com (Kent Dickey) writes:
[snip]
>> All structs must be typedef'ed and the typedef name is an initial capital.
>
>I try to follow the rule that all (developer-chosen) type names
>start with a capital letter, and no other names do. (Preprocesor
>symbols are treated separately.)
>
>
>> All structs are created by STRUCT(Sample_structure) where STRUCT is:
>> #define STRUCT(a) typedef struct a ## _st a; struct a ## _st
>
>It is a little bit safer if STRUCT(a) were defined
>
> #define STRUCT(a) \
> struct a ## _st; typedef struct a ## _st a; struct a ## _st
>
>The reasons are somewhat esoteric. But since the leading
>declaration is hidden inside a macro, it seems better to use the
>safer form.

What are the reasons? It's not obvious to me what it is, but I would
guess it's some sort of namespace conflict you're trying to avoid.

[big snip]

>> All names use _ and not CamelCase.
>
>Generally using underscores is better than either CamelCase or
>camelCase, for ergonomic reasons. An exception is type names,
>where for example TreeNode arguably reads better than Tree_node.
>(The type-name exception tacitly assumes that type names are
>limited to at most four or five words; more than that runs
>into readability problems.)

Most structs are "File-related-prefix" and then "description". So
Serial_bufferinfo, Disk_params, etc.
I cannot imagine using more than 3 words, just 2 words is pretty long.

>
>> All #defines are all-caps. No other identifier can be all-cap.
>> "#define NUM_THINGS 5" is fine. #define FUNC_THIS(a) must have
>> "(a)" on the right hand side in all instances. Anything more complex
>> than a single number or variable must wrap the definition with ().
>
>Generally yes; there may be exceptions in some special cases.
>
>
>> Function names include the file name (or a short form of it) as a prefix.
>> So serial.c would have serial_init(), serial_out_char(), etc.
>> But windows_serial.c could be wser_init(), etc, just to shorten things.
>> All functions in one file must use the same prefix.
>
>Having a prefix seems reasonable. Insisting that the prefix be
>tied to the file name seems excessive.

I can return to code I wrote 20 years ago and navigate it manually without
grep. I use abbreviations, so customer_input.c would name the functions
ci_().

>> I have a simple hungarian notation: 64-bit variables have a 'd' in the name
>> that is meaningful: "dval", "init_dtmp". "do_this" is not 64-bit.
>> Pointers have "ptr" in the name somewhere, often at the end (but
>> "userptr2" is fine), except char * pointers should use "str" in the
>> name somewhere. Non pointers variables never have str or ptr
>> in the name. For your app, try to use consistent names: Don't let
>> "val" be unsigned sometimes and signed other times. Pick a convention
>> and stick with it. I like val to be unsigned, and tmp to be signed.
>> So last_val is unsigned, and prev_tmp is an int.
>> Loop counters can be i,j,k, but all other variables should briefly
>> describe what it is. "tmp" or "val" are only ok for brief usage.
>
>IMO encoding the type of a variable in its name is just wrong.
>If a function has so many names that it's difficult to remember
>what types go with which names then the function is too big. For
>global names or struct members, if knowing the types is any
>significant burden then any uses of those names should be
>encapsulated, reducing their surface area.

My rules are a pushback against needless abstraction. The idea is I can
read a line of code, and have a very good idea of what it's doing without
having to chase down the declarations of the function definition. For
example:

foo(a, b, c, d);

could be passing 4 integers. It could be passing 4 arrays. It could be
passing two function pointers, and integer, and a struct.

With my style, it has to be passing 4 integers (of some size). This is
why passing an array has to do &a[0], since 'a' could mean anything. It
also makes it clear that the array needs some sort of size to be passed
as well. Passing a structure is always:

Thing my_thing;

...
foo(&my_thing);

where & and a variable is almost always a struct, can be an integer rarely.

>> Declaring variables never initializes them, except for global variables.
>> Use -Wall -Werror to ensure everything is initialized. This is so
>> the declarations can be ignored when reading code since they
>> provide no new information.
>
>Interesting argument. I may try adopting this rule for a while.
>
>
>> When passing around an array, always use &array[0] notation to indicate
>> "array" is an array and not a pointer.
>
>I follow a different rule: 'array' by itself means the whole
>array, '&array[0]' means just the one element is referenced.

I get that, but I want to never be confused about passing around
an array vs. an integer. A lot of my rules are in reaction to reading large
programs, like Linux, where you have to have lots of windows open looking
at headers to even get a vague idea what's going on in one function.

>> The advantage of this is you can begin reading any file and have an idea
>> what functions it's calling and even what work it's doing, without
>> having to constantly look at header files or variable declarations. And
>> the light Hungarian notation means you don't have to read declarations,
>> so I pack them tightly with many variables per line just to be done with
>> them. Variables are declared in order by type: arrays, then pointers,
>> then ints, and by size within each type. It's not legal to mix pointers
>> and ints in declarations, so you cannot do: "int a, *ptr1, b, c[100];"
>
>My sense is that these motivations assume a style of coding that
>is different from my usual style(s). And hence, consequently,
>work better in some coding/development styles than others. It
>would be interesting to explore that question further at some
>point.
>
>
>> I use special typedefs for unsigned types: byte, word16, word32, and dword64
>> of the obvious sizes. These are the only typedefs that are not structures
>> and are not capitalized. I'm less likely to mix them up since byte,
>> word32, and dword64 are all different lengths and multiple keystrokes
>> apart: word64 and dword32 are not valid. It's hard to tell uint32_t
>> from uint64_t, they tend to blend together to my eyes in large
>> structures, and getting them mixed up is a very annoying bug.
>
>IMO using type names like word32 or dword64 (or uint32_t or
>uint64_t) in open code is generally a bad idea. So here again I
>expect that the efficacy of these particular rules depends on
>program style on a larger scale.

I'm trying to put some protective pads on to avoid C's many pitfalls,
and make it easy to browse code, even without complex tools. I'm interested
in learning other strategies, but I find most coding guidelines try to
do some useful things, but then don't really achieve it due to pushback,
so you have the worst of all worlds: constraints that annoy everyone without
much benefit.

Perl had the motto "There's more than one way to do it", and my reaction
is that's a bad thing. It's just too hard to deal with a code base
using so many language features that no one really understands. And
"don't do this" lists end up reinforcing bad ways, since you're
basically saying "Don't think about flowers", and then everyone
thinks about flowers. If you say "don't use goto", everyone starts
thinking of ways to use goto. But if you say, "handle errors by
returning negative numbers, and never return negative numbers
otherwise", you don't reinforce all the other ways to do it.

Kent

Kaz Kylheku

unread,
Sep 13, 2022, 1:38:40 AM9/13/22
to
Like that silly POSIX with its pthread_mutex_attr_t cruft and whatnot.

OK, we are in POSIX, so the "p" is redundant, right?

Mutexes are owned by threads; so the "thread" is redundant.

Just mutex_lock, mutex_timedwait, mutex_t, mutex_attr_t, ...

posix_spawn is another stupidity; at least shorten it to pspawn, if
you don't want to clash with someone's spawn identifier.

aio_read could have been named posix_asyncio_read, but someone
had the good sense to refrain.

On a tangentially related topic, I could never use these buggered
languages with hierarchical modules:

com.asshole.vendor.shit.library.sys.io.print("up yours!")

Good grief, on what planet is anything of the sort a good idea.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Tim Rentsch

unread,
Sep 13, 2022, 8:18:52 AM9/13/22
to
ke...@provalid.com (Kent Dickey) writes:

> In article <86edwgp...@linuxsc.com>,
> Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
>
>> ke...@provalid.com (Kent Dickey) writes:

[..largely condensed..]

>>> All structs are created by STRUCT(Sample_structure) where STRUCT is:
>>> #define STRUCT(a) typedef struct a ## _st a; struct a ## _st
>>
>> It is a little bit safer if STRUCT(a) were defined
>>
>> #define STRUCT(a) \
>> struct a ## _st; typedef struct a ## _st a; struct a ## _st
>>
>> The reasons are somewhat esoteric. But since the leading
>> declaration is hidden inside a macro, it seems better to use the
>> safer form.
>
> What are the reasons? It's not obvious to me what it is, but I would
> guess it's some sort of namespace conflict you're trying to avoid.

It's common to think of 'typedef struct some_tag SomeTypeName;'
as doing two things, namely, introducing a new structure tag, and
giving an alternate name to a struct type having that tag. What
actually happens is not exactly that. The point of putting in
the leading 'struct a ## _st;' is to ensure that a new tag is
introduced into the relevant scope, rather than possibly reusing
an existing structure tag defined in an outer scope. Basically
the point of having 'struct a ## _st;' is to make sure that the
following 'typedef struct a ## _st a;' behaves the way people
expect it to behave, and not be blindsided by different behavior
when the structure tag accidentally matches a tag defined in an
outer scope.

>> [...]
>
> My rules are a pushback against needless abstraction. [...]

Whether an abstraction is needless is a subjective question. It
seems to me that (some of) the rules you proprose effectively
prevent any abstraction in some cases, whether it is "needless"
or not.

>> [...]
>
> I'm trying to put some protective pads on to avoid C's many
> pitfalls, and make it easy to browse code, even without complex
> tools. [...]

I'm not sure what kinds of tools you count as "complex tools".
Do you mean to avoid using any of the standard utilities that
were part of Unix 40+ years ago? To me it seems silly to design
rules assuming such a primitive environment (that is, one where
the common Unix utilities of circa 1980 were not present).

One question for you: looking over your own code, what would
you say is a rough distribution of function lengths? What is the
range of lengths, what is the average length, what is the median
length? If you can get exact numbers, so much the better, but
rough guesses (assuming they are informed guesses) are fine.

Scott Lurndal

unread,
Sep 13, 2022, 9:30:38 AM9/13/22
to
At the time when the Posix 1003.4 working group was standardizing
a threading interface, there were already several competing
unix-based threading implementations existing. None of which
had the same API or API semantics (e.g. DIGITAL threads or
System V 4.2 M-N threads, or SunOs threads). Therefore, using 'mutex_',
'thread_' prefixes would have conflicted with existing proprietary
implementations. Thus, the nomenclature you're complaining
about was developed to avoid conflicts with existing code.

>
>posix_spawn is another stupidity; at least shorten it to pspawn, if
>you don't want to clash with someone's spawn identifier.

Stupid is a pretty strong word for someone who wasn't there at
the time.

Kent Dickey

unread,
Sep 13, 2022, 6:55:33 PM9/13/22
to
In article <86a673p...@linuxsc.com>,
I always keep STRUCT() at top (file) scope, but I'll keep this in mind.

>>> [...]
>>
>> My rules are a pushback against needless abstraction. [...]
>
>Whether an abstraction is needless is a subjective question. It
>seems to me that (some of) the rules you proprose effectively
>prevent any abstraction in some cases, whether it is "needless"
>or not.
>
>>> [...]
>>
>> I'm trying to put some protective pads on to avoid C's many
>> pitfalls, and make it easy to browse code, even without complex
>> tools. [...]
>
>I'm not sure what kinds of tools you count as "complex tools".
>Do you mean to avoid using any of the standard utilities that
>were part of Unix 40+ years ago? To me it seems silly to design
>rules assuming such a primitive environment (that is, one where
>the common Unix utilities of circa 1980 were not present).
>
>One question for you: looking over your own code, what would
>you say is a rough distribution of function lengths? What is the
>range of lengths, what is the average length, what is the median
>length? If you can get exact numbers, so much the better, but
>rough guesses (assuming they are informed guesses) are fine.

Unix 1980's stuff is fine, but I don't want to rely on cscope, syntax
highlighting and other IDE stuff if I don't need it.

You can see code that mostly meets my style definitions at:
http://kegs.sourceforge.net/kegs.1.16.tar.gz (some was written almost 30
years ago and doesn't meet the style guidelines and I have not fixed all
the problems yet, mostly function and global variable naming issues). All my
functions look like:

return_type
function_name(arguments here)
{
...
}

(Primarily to make [[ and ]] work in vi, but it also makes many code grep's
easier, the definition of serial_init is /^serial_init in vi).

So I can find the number of functions with:
grep '^}$' *.c | wc
and the total lines:
wc *.c

and I get 36747/756 = 48.6 lines per function (counting all overhead outside
the functions as well). ts=8.

Kent

Chris M. Thomasson

unread,
Sep 13, 2022, 7:58:44 PM9/13/22
to
[...]

Side note, Kegs is great!

Tim Rentsch

unread,
Sep 14, 2022, 11:05:18 AM9/14/22
to
ke...@provalid.com (Kent Dickey) writes:

> In article <86a673p...@linuxsc.com>,
> Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
>
>> ke...@provalid.com (Kent Dickey) writes:
>>
[...]
>>> I'm trying to put some protective pads on to avoid C's many
>>> pitfalls, and make it easy to browse code, even without complex
>>> tools. [...]
>>
>> I'm not sure what kinds of tools you count as "complex tools".
>> Do you mean to avoid using any of the standard utilities that
>> were part of Unix 40+ years ago? To me it seems silly to design
>> rules assuming such a primitive environment (that is, one where
>> the common Unix utilities of circa 1980 were not present).
>>
>> One question for you: looking over your own code, what would
>> you say is a rough distribution of function lengths? What is the
>> range of lengths, what is the average length, what is the median
>> length? If you can get exact numbers, so much the better, but
>> rough guesses (assuming they are informed guesses) are fine.
>
> Unix 1980's stuff is fine, but I don't want to rely on cscope,
> syntax highlighting and other IDE stuff if I don't need it.

Same here.

> You can see code that mostly meets my style definitions at:
> http://kegs.sourceforge.net/kegs.1.16.tar.gz (some was written
> almost 30 years ago and doesn't meet the style guidelines and I
> have not fixed all the problems yet, mostly function and global
> variable naming issues).

Thank you, it's good to have this example. I should look at it more
closely but perusing it lightly it looks like your layout choices
are close to my own.

> All my functions look like:
>
> return_type
> function_name(arguments here)
> {
> ...
> }

Same here, except I put the open brace immediately after the
close parenthesis of the function line.

> (Primarily to make [[ and ]] work in vi, but it also makes many
> code grep's easier, the definition of serial_init is /^serial_init
> in vi).

Right. I use emacs but the idea is the same.

> So I can find the number of functions with:
> grep '^}$' *.c | wc
> and the total lines:
> wc *.c
>
> and I get 36747/756 = 48.6 lines per function (counting all
> overhead outside the functions as well). ts=8.

Some time ago I wrote a short awk script to tabulate function
statistics. Running that on your .c sources gives an average of
about 39 lines per function (this measure counts only those lines
inside the outer function braces), with about 9.5% blank lines
(again inside function braces). To give some ranges, individual
files range from about 5% to just over 18% blank lines (there is
one outlier at 3%), and these number match my own rule of thumb
of between 5% and 20% blank lines. The range of average lines
per function goes from about 15 lines/function to about 66
lines/function, with one outlier of about 86 lines/function.

For contrast, my own code typically falls in the range of 10-15
lines/function average; anything over 20 (average; individual
functions can be longer) or so indicates a need to look at
refactoring.

Jonathan Harston

unread,
Sep 27, 2022, 9:02:14 AM9/27/22
to
On Sunday, August 28, 2022 at 12:06:12 AM UTC+1, Thiago Adams wrote:
> I am searching for C naming conventions.
...
> Any link? What are the "classic ones? "
> I think one sample is "Win32" API

I aim to consistently use the Big_SmallSmaller scheme, which is the opposite
of the Win32 API. The WinAPI really irritates me, I don't what to know all the
Set* functions when I'm trying to deal with, eg, a Cutter system, I want to know
all the Cutter functions. Using Big_SmallSmaller give me, eg:
Cutter_Init
Cutter_Write
Cutter_Read
Cutter_Copy
Cutter_CopyBuffer
etc., and I use Big_smallsmaller for variables, eg:
Cutter_buffer
Cutter_timeout

whereas the WinAPI naming scheme gives me
InitCutter
InitLCD
InitDiskSubsystem
InitKeyboard
InitSomethingElse
InitAnotherSThing
I don't *CARE* what all the Init calls are. Where the hell are the other
Cutter calls?, I have to *GUESS* them.

For reference, Big_SmallSmaller is used by RISC OS.

jgh

John Bode

unread,
Sep 30, 2022, 2:02:52 PM9/30/22
to
On 8/27/22 6:06 PM, Thiago Adams wrote:
> I am searching for C naming conventions.
> For instance, how to name structs, function, global variables...
>
> Any link? What are the "classic ones? "
>
> I think one sample is "Win32" API

All naming conventions suck. All brace style conventions suck. Anyone
can make good arguments for or against any convention you pick.

The only things you really have to worry about are:

- Names beginning with "_" and "__" are reserved for the
implementation - don't use them in your code;

- Type names ending in "_t" reserved under POSIX - don't use it for
any user-defined types;

Beyond that, go nuts. As long as your names are meaningful and convey
usage properly, the form of that name shouldn't matter, although I will
say Hungarian notation is an abomination and everyone uses it wrong
anyway.

Kaz Kylheku

unread,
Sep 30, 2022, 2:32:51 PM9/30/22
to
On 2022-09-30, John Bode <jfbod...@gmail.com> wrote:
> On 8/27/22 6:06 PM, Thiago Adams wrote:
>> I am searching for C naming conventions.
>> For instance, how to name structs, function, global variables...
>>
>> Any link? What are the "classic ones? "
>>
>> I think one sample is "Win32" API
>
> All naming conventions suck. All brace style conventions suck. Anyone
> can make good arguments for or against any convention you pick.
>
> The only things you really have to worry about are:
>
> - Names beginning with "_" and "__" are reserved for the
> implementation - don't use them in your code;
>
> - Type names ending in "_t" reserved under POSIX - don't use it for
> any user-defined types;

POSIX claiming _t means next to nothing.

They are just saying that POSIX will introduce new typedef names in this
space, which will steamroll any same named identifier of yours.

But! Historically, revisions of POSIX have not confined themselves to
previously documented namespaces.

In other words, the POSIX committee will run over any identifier
whatsoever that pops into their heads in the future, whether in
a previously reserved space or not.

You have to be prepared for a new version of POSIX to clash with
identifier in your program in any case, whether you use _t or not.

So pretty much it is safe to ignore it and use _t for your own
typedef names.

Suppose you are tryinjg to name a type and don't know whether to
choose asdfhjkl_t or asdfhjkl.

The likelihood that POSIX will clash with asdfhjkl in the future
is *greater* than that it will clash with asdfhjkl_t, because
the former belongs to a more general, more populous namespace in which
names are created more frequently.

One thing you can do is try not to introduce typedef names in local
scopes, so then if a clash shows up, it will be a straight global
redefinition that is diagnosed --- as opposed to some macro hygiene
issue that might cause an undiagnosed problem.

Say that some POSIX macro references a _t typedef name. E.g. in a cast
expression or whatever. If you use that macro in a local scope in
which you also redefine that type locally, you have unwanted
capture: the macro expansion now refers to your own _t name, with
whatever consequences. The POSIX macro arguably then relies on the
reserved space for hygiene which you broke.

POSIX functions have the same problem anyway. Say POSIX introduces
some new function asdfjkl and has a macro whose expansion calls it.
You have a function argument asdfgjkl in the scoipe of that macro,
and that argument is a function pointer which can be called
with allt he same arguments!

#define posix_macro do { ... asdfghkl(str) ... } while (0)

void mycode(void (*asdfgjkl)(const char *), int other_arg)
{
posix_macro(other_arg); // oops
}

Well written system headers prevent this by referring to aliases
in the __ namespace. A non-idiot implementor of POSIX will
have it like this:

#define posix_macro do { ... __internal__asdfghkl(str) ... } while (0)

and that should be done for type names, __foo_t and not foo_t,
regardless of the stupid _t namespace thing granted by the spec.

Ben Bacarisse

unread,
Sep 30, 2022, 7:54:29 PM9/30/22
to
John Bode <jfbod...@gmail.com> writes:

> On 8/27/22 6:06 PM, Thiago Adams wrote:
>> I am searching for C naming conventions.
>> For instance, how to name structs, function, global variables...
>> Any link? What are the "classic ones? "
>> I think one sample is "Win32" API
>
> All naming conventions suck. All brace style conventions suck.
> Anyone can make good arguments for or against any convention you pick.
>
> The only things you really have to worry about are:
>
> - Names beginning with "_" and "__" are reserved for the
> implementation - don't use them in your code;

There are way more than that! For example 'string' (with external
linkage) is reserved and EIEIO is reserved if you include certain
headers. The C23 draft has a handy list of patterns to avoid.

--
Ben.

Kaz Kylheku

unread,
Oct 1, 2022, 4:11:44 AM10/1/22
to
The difference between the leading underscores and "str" and "E",
is that the latter are in a future expansion area of a public namespace.
If they were to appear, they would be documented as new identifiers in
the standard, or else a vendor's extension, like GNU "strfry".

Whereas _ and __ identifiers are a churning toilet bowl. Implementors
invent these at the drop of a hat in any situation they need a
hidden name for any reason that must not clash with application code
in any conceivable way.. E.g. in macro hygiene and whatever.

For instance, a vendor is not going to use "string" as the name of a
local variable generated by a macro, for the sake of hygiene; but they
will use __str, __string, __s and whatever not..

The _ and __ namespaces demand respect in a way that E and str
do not.

Kaz Kylheku

unread,
Oct 1, 2022, 4:12:36 AM10/1/22
to
On 2022-10-01, Blue-Maned_Hawk <bluema...@gmail.com> wrote:
> Content-Type: text/plain; charset=UTF-8; format=flowed
> Content-Transfer-Encoding: base64

s/flowed/flawed/

Scott Lurndal

unread,
Oct 1, 2022, 12:26:16 PM10/1/22
to
Kaz Kylheku <864-11...@kylheku.com> writes:
>On 2022-09-30, John Bode <jfbod...@gmail.com> wrote:
>> On 8/27/22 6:06 PM, Thiago Adams wrote:
>>> I am searching for C naming conventions.
>>> For instance, how to name structs, function, global variables...
>>>
>>> Any link? What are the "classic ones? "
>>>
>>> I think one sample is "Win32" API
>>
>> All naming conventions suck. All brace style conventions suck. Anyone
>> can make good arguments for or against any convention you pick.
>>
>> The only things you really have to worry about are:
>>
>> - Names beginning with "_" and "__" are reserved for the
>> implementation - don't use them in your code;
>>
>> - Type names ending in "_t" reserved under POSIX - don't use it for
>> any user-defined types;
>
>POSIX claiming _t means next to nothing.
>
>They are just saying that POSIX will introduce new typedef names in this
>space, which will steamroll any same named identifier of yours.
>
>But! Historically, revisions of POSIX have not confined themselves to
>previously documented namespaces.
>
>In other words, the POSIX committee will run over any identifier
>whatsoever that pops into their heads in the future, whether in
>a previously reserved space or not.

I've been part of the Open Group (nee POSIX) technical committee
since the early 1990's, and what you state could not be further
from the truth.

0 new messages