Live data from Hacker News

My personal C coding style as of late 2023

nullprogram.com

191–200 of 466 posts

Re: My personal C coding style as of late 2023

#192
post #187

Earlier quoted context omitted.

> Wouldn’t existing programs just continue working? Only ones which don't have variables named `i8` or `b32` (which is common, but not for booleans). I've seen many projects which used the pattern [a-z][1-9]+ as variables. Those programs with a variable called `i8` won't compile if the standard made a type called `i8`. In particular, the standard reserves entire patterns to itself, so it cannot reserve the pattern of…

But that problem exists for any C project that uses an external library. If the library defines something that the project already uses, then the project will not work. In my mind that's not a problem with the decisions taken by the author of the article, it's more of a symptom of C's limitations.

> But that problem exists for any C project that uses an external library. If the library defines something that the project already uses, then the project will not work.

For libraries, yes, but we're talking about why the standard didn't do it.

The standard did not want[1] to reserve keywords that current programs were already using.

A library that conflicts on keywords will only break with those programs that use it. A standard that conflicts on keywords breaks all programs in that language.

> In my mind that's not a problem with the decisions taken by the author of the article, it's more of a symptom of C's limitations.

One of the constraints of taking decisions is to work within the limits existing framework - if you're avoiding the alternatives that don't break, then it's the decision-makers bug, not the frameworks.

The framework has limitations, widely published and known. You make decisions within those limitations.

[1] Although, they do do it, it's only with relectance, not on a whim to avoid typing a few characters)

Re: My personal C coding style as of late 2023

#193
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…

> (size)(sizeof(x)[y])

Actually, and this is probably surprising to many, this is equivalent to

    (size)(sizeof ((x)[y]))
sizeof is not a function but a unary operator, and indexing (as well as function calling...) binds stronger than the sizeof operator. It is not a function, not even syntactically! Hence why I strongly prefer putting a space after the sizeof keyword, and to not use parens for the operand unless needed.

https://en.cppreference.com/w/c/language/operator_precedence

So the "correct" way to define the macro is

#define sizeof(x) ((size)(sizeof (x)))

Re: My personal C coding style as of late 2023

#194

Earlier quoted context omitted.

> Wouldn’t existing programs just continue working? Only ones which don't have variables named `i8` or `b32` (which is common, but not for booleans). I've seen many projects which used the pattern [a-z][1-9]+ as variables. Those programs with a variable called `i8` won't compile if the standard made a type called `i8`. In particular, the standard reserves entire patterns to itself, so it cannot reserve the pattern of…

No program should every have variables names according to [a-z][1-9]+ pattern, except perhaps loop indices - and not even then.

> No program should every have variables names according to [a-z][1-9]+ pattern, except perhaps loop indices - and not even then.

What's that got to do with not breaking existing programs?

Re: My personal C coding style as of late 2023

#195
post #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.

> Because C's precedence rules are damn complicated.

This particular part is not actually complicated: the postfix operators bind the most tightly, then the prefix ones, then the infix ones. (The last part is quite messy, though.)

So (int)x[y] parses the same way as, for example, *p++, which should be familliar to a C programmer.

Re: My personal C coding style as of late 2023

#196
post #165

Earlier quoted context omitted.

Wouldn’t existing programs just continue working? What the author did was adding new types, not modifying or removing existing ones.

> Wouldn’t existing programs just continue working? Only ones which don't have variables named `i8` or `b32` (which is common, but not for booleans). I've seen many projects which used the pattern [a-z][1-9]+ as variables. Those programs with a variable called `i8` won't compile if the standard made a type called `i8`. In particular, the standard reserves entire patterns to itself, so it cannot reserve the pattern of…

Typedefs and variable namens don't live in them same namespace, do they?

Re: My personal C coding style as of late 2023

#197

Earlier quoted context omitted.

> carrying bit length in the name is critical I beg to disagree. In D: byte - 8 bits short - 16 bits int - 32 bits long - 64 bits absolutely nobody is confused about this.

Because we've used those names since forever, but that's archaic random crap really. Nothing apart from maybe "byte" makes sense here, the rest is completely arbitrary historic cruft. Could as well have called the rest timmy, britney and hulk.

Java uses exactly the same, and has a huge developer mindshare. While rooted in historic accidents, it's well-established.

Re: My personal C coding style as of late 2023

#198
post #133
post #98

Earlier quoted context omitted.

Eh, I hard disagree with this memo. He's either dismissing or unaware of the biggest advantage of unsigned types, namely they make invalid state unrepresentible. And essentially all of his criticism of unsigned types is really criticism of the sloppy way old C and C++ compilers let you mix signed and unsigned numbers in math operations. Modern C/C++ compilers can and will warn you (quite aggressively) if you mix sign…

The advantage of using signed types is that you can reliably find overflow bugs using UBSan and protect against exploiting such errors by trapping at run time. For unsigned types, wrap-around bugs are much harder to find and your program will silently misbehave.

With unsigned you can actually check for overflow yourself very easily

  z=x+y; if(z 
And bounds checks are just a single comparisons against an upper bound (handles both over and underflow)

  size = x + y;
  // or
  size = x - y

  if(size 
Prior to C23 (stdckdint.h) its very error prone to check for signed overflow since you have to rearrange equations to make sure no operation could ever possibly overflow.

Re: My personal C coding style as of late 2023

#200
post #113

I wrote and still maintain an open source C project for 20+ years. Once a year I get a new guy coming in and telling me I am doing it wrong: you should typedef all data types, you should stop using const, and so on. It stopped being funny after the first couple times.

I'm not a C developer, so I have to ask: why in the world would you not use const?
Post reply on HN