Live data from Hacker News

My personal C coding style as of late 2023

nullprogram.com

41–50 of 466 posts

Re: My personal C coding style as of late 2023

#41
post #29

> signed sizes are the way Well, I should probably just say "We're done here." and stop reading the rest of the article. "Signed sizes" are an extremely surprising abstraction break that are just asking for disaster. > No const. It serves no practical role in optimization, and I cannot recall an instance where it caught, or would have caught, a mistake. Should you even be writing C if you haven't hit this? People mix…

The no-const people will never be satisfied, so just use const as necessary, propagate as required, and ignore them when they complain. If they take it out, put it back in. They'll always get bored first. I've been doing this for 25 years, and I'm still here.

(The static thing might depend on the tooling. I went static-by-default about 15 years ago, around the same time I went full size_t, and I've yet to have a problem with it.)

Re: My personal C coding style as of late 2023

#42

I might just be a grumpy old dev but a lot of this stuff gets an immediate no from me because it’s so unidiomatic. You have to unlearn the accepted way of doing things and you end up with a codebase that is just so foreign to anyone looking at even a small chunk of it, unless they are committed to really learning to do things your way. Everyone knows what a uint32_t is when they see it. The cognitive overhead (until…

To be fair they did say that when contributing to a shared project they follow the prevailing standard.

I don’t see the harm in following this for your own passion projects. You aren’t doing it for the world, you’re doing it for yourself.

Re: My personal C coding style as of late 2023

#43
> #define sizeof(x) (size)sizeof(x)

Undefined behavior[1]

> #define assert(c) while (!(c)) __builtin_unreachable()

Undefined behavior[1]

> I’ll cast away the const if needed.

Undefined behavior[2]

> The assignments are separated by sequence points, giving them an explicit order.

I don't believe assignments are sequence points and only the function call is.

[1] https://en.cppreference.com/w/c/language/identifier#Reserved...

[2] https://en.cppreference.com/w/c/language/const

Re: My personal C coding style as of late 2023

#44

I might just be a grumpy old dev but a lot of this stuff gets an immediate no from me because it’s so unidiomatic. You have to unlearn the accepted way of doing things and you end up with a codebase that is just so foreign to anyone looking at even a small chunk of it, unless they are committed to really learning to do things your way. Everyone knows what a uint32_t is when they see it. The cognitive overhead (until…

[deleted]

Re: My personal C coding style as of late 2023

#46
post #40

> #define sizeof(x) (size)sizeof(x) Technically, it's illegal to #define over a language keyword.

Also, `#define countof(a) (sizeof(a) / sizeof(*(a)))` is unsafe since the arg is evaluated twice.

This is a very common macro to get static array lengths and i'm not sure there is any other way to do the same thing (i.e. give a static array, get back the number of items in it) in any other way.

Re: My personal C coding style as of late 2023

#47
post #33

> #define sizeof(x) (size)sizeof(x) I'm guessing this is lacking an outer pair of parentheses (i.e. it's not `((size)sizeof(x))`) on the grounds that they're unnecessary. In terms of operator precedence, casting binds tightly, so if you write e.g. `sizeof(x) * 3`, it expands to `(size)sizeof(x) * 3`, which is equivalent to `((size)sizeof(x)) * 3`: the cast happens before the multiplication. Indeed, casting binds more…

That's a good catch. The moral of the story is that unless your macro definition expands to a single token (e.g #define X 123) you should always, always, always surround it with parenthesis. Because C's precedence rules are damn complicated.

Re: My personal C coding style as of late 2023

#48
post #43

> #define sizeof(x) (size)sizeof(x) Undefined behavior[1] > #define assert(c) while (!(c)) __builtin_unreachable() Undefined behavior[1] > I’ll cast away the const if needed. Undefined behavior[2] > The assignments are separated by sequence points, giving them an explicit order. I don't believe assignments are sequence points and only the function call is. [1] https://en.cppreference.com/w/c/language/identifier#Reser…

> #define assert(c) while (!(c)) __builtin_unreachable()

And people keep telling me that nobody uses the C preprocessor to define their own syntax any more!

Re: My personal C coding style as of late 2023

#49
post #39

I like it a lot. Especially the part about ditching const qualifiers. They clutter function declarations, don't make the intent any clear, and almost never improve performance. Restrict, on the other hand, I've found makes the compilers emit better code in many cases. But I don't like using 1 and 0 instead of booleans. Many standard C functions (fclose for example), return 0 on success. Better to be explicit here.

I like using the const keyword, and believe it serves a real purpose with readability. I feel like most things are read access by default which is why it seems cluttered. I believe rust gets immutable by default correct .

Re: My personal C coding style as of late 2023

#50
post #35
post #21

Earlier quoted context omitted.

It depends entirely on the architectures | CPUs, that said the obvious case from past experience is numeric processsing jobs where (say) you flow data into "per cycle" structs that lead with some conditionals and fill out with (say) 512 | 1024 | 2048 sample points for that cycle (32 or 64 bit ints or floats) .. the 'meat' of the per cycle job. My specific bug bear here was a junior who insisted "saving space" by pack…

But if you don't use packed attributes, then the compiler will still add padding as necessary to avoid misalignment, while not wasting space when that's not necessary.

The key part (for myself) of ForkMeOnTinder's comment was:

> Maybe I'm a beginner then. He lists a few cases where it's not worse than sticking to 8-bit bools, but no cases where it's actually an improvement. It still wastes memory sometimes

They key part of my response is sometimes "wasting memory" (to gain alignment) is a good thing.

If someone, a beginner, is concerned about percieved wasted memory then of course they will use "packed".

As for the guts of your comment, I agree with your sentiment but would exercise caution about expecting a compiler to do what you expect in practice - especially for cross architectural projects that are intended to be robust for a decade and more - code will be put through muliple compilers across multiple architectures and potentially many many flags will be appied that may conflict in unforseen ways with each other.

In general I supported the notion of sanity check routines that double check assumptions at runtime, if you want data aligned, require data to be big endian or small endian etc then have some runtime sanity checks that can verify this for specific executables on the target platform

Post reply on HN