Live data from Hacker News

My personal C coding style as of late 2023

nullprogram.com

431–440 of 466 posts

Re: My personal C coding style as of late 2023

#431

Earlier quoted context omitted.

Yeah, almost the only time I'm writing C anymore is embedded, where I want to reason about type widths (while taking on as light a cognitive load as is possible). I have enough code that gets compiled to an 8, 16, or 32 bit target depending on context that having the bit width right on the tin is valuable. And it doesn't even cost me "hours and hours".

Also: Embedded is almost the only time you really, truly need to care about how many bits a type is, and only when you're interacting with actual hardware. For almost every other routine task in programming, I would argue that it really doesn't matter if your int is 32 bits wide or 64 bits wide. Why go through the trouble of insisting on int32_t or int64_t? It probably doesn't matter for the things you are counting.…

Sizing values is also great for reducing bandwidth footprint, either network or memory. The really good optimizations come from this.

Re: My personal C coding style as of late 2023

#432

Earlier quoted context omitted.

> This is not true if a , b and c are unsigned True, but this is not valid if they are signed, either. Take a = INT_MIN b = 1 c = 2 Then a is true. But a - b invokes undefined behavior. Edit: missed > Say that a, b and c are small integers (we don't worry about addition overflow) Ah, well that makes this example vacuously true, however I'm not sure what the utility in that restriction is. We've only moved the goalpos…

> however I'm not sure what the utility in that restriction is. We have moved the goalposts much farther apart. If we are using a 32 bit integer type, all we need is that a , b and c fit into 31 bits. Then there is no way that b + c or a - b overflow. For a single addition or subtraction, we just need one bit of headroom. I.e. the values do not actually have to be that small. There are all kinds of situations in whic…

If b = 0x7fffffff and c = 0x7fffffff, b and c both fit in 31 bits, and b + c overflows to -2 in signed int32 twos-complement math (I think).

If b = 0x40000000 and c = 0x40000000, b and c both fit in 31 bits, and b + c overflows to -2147483648 in signed int32 twos-complement math (I think).

Maybe the definition of "32 bit integer type" you're using is meant to encompass only 32 bits as all unsigned (but then there are a - b terms that would overflow if b > a).

Or perhaps I've gotten something else wrong.

Re: My personal C coding style as of late 2023

#433

Earlier quoted context omitted.

> however I'm not sure what the utility in that restriction is. We have moved the goalposts much farther apart. If we are using a 32 bit integer type, all we need is that a , b and c fit into 31 bits. Then there is no way that b + c or a - b overflow. For a single addition or subtraction, we just need one bit of headroom. I.e. the values do not actually have to be that small. There are all kinds of situations in whic…

If b = 0x7fffffff and c = 0x7fffffff, b and c both fit in 31 bits, and b + c overflows to -2 in signed int32 twos-complement math (I think). If b = 0x40000000 and c = 0x40000000, b and c both fit in 31 bits, and b + c overflows to -2147483648 in signed int32 twos-complement math (I think). Maybe the definition of "32 bit integer type" you're using is meant to encompass only 32 bits as all unsigned (but then there are…

> b and c both fit in 31 bits

They don't fit into a 31 bit two's complement (i.e. signed) representation, in terms of representing their interpretation as the familiar 32 bit INT_MAX.

31 bit two's complement goes from -0x40000000 to 0x3FFFFFFF. There is a 0x7FFFFFFF bit pattern, which represents -0x00000001. It has a sign bit which is 1. (So, adding that to itself does go to -2, but under that interpretation there is no overflow.)

Any pair of values in that range can be added or subtracted in 32 bit two's complement.

Including the most negative value: -0x40000000 + -0x40000000 = -0x80000000.

Re: My personal C coding style as of late 2023

#434

Earlier quoted context omitted.

Why would we ever need 128-bit CPUs? I remember the PS2 had something like that (with details and caveats I don't understand), but subsequent games consoles went back to a more usual register size: https://en.wikipedia.org/wiki/128-bit_computing

All I know is we keep having this issue with saying "nah, this is it. Nobody will ever need more than this." And then inevitably the time comes when we need more.

Back in the 80s, 16 bit programmers knew that 32 bit code was coming, so they carefully crafted the code to be portable to 32 bits.

Of course, none of it worked on 32 bit machines because the programmers had never written 32 bit code before and did the portability measures all wrong.

Re: My personal C coding style as of late 2023

#435

Earlier quoted context omitted.

Wait... where's plain "long"? I know, you probably know, but that is why you use explicit sizes where you can.

I quit using "long" because sometimes a long is 32 bits and sometimes 64, and I can never remember which compiler does which. But "int" is 32 bits and "long long" is always 64 bits, so that's what I stick with. C's "long" should not be used in new code.

The type that is 32 bits in C is int32_t, and the 64 bit one is int64_t; if you really want those specific widths, you can just use those types.

The type long is the smallest ranking basic type that is at least 32 bits wide. Since int is only required to go to 32767, you use long if you need a signed type with more range than that. That made a lot of sense on platforms where int really did go up to just 32767, and long provided the 32 bit one.

Now long, while at least 32 bits, is not required to be wider than 32; if you need a signed type that goes beyond 2147483647, then long long is it.

Those are the portability rules. Unfortunately, those rules will sometimes lead you to choose types that are wider than necessary, like long when int would have worked.

Where that matters, it's best to make your code tunable with your own typedefs. I don't mean typedefs like i32 but abstract ones, like ISO C's time_t or clock_t, or POSIX's pid_t. You can adjust your types without editing numerous lines of code.

Re: My personal C coding style as of late 2023

#436

Earlier quoted context omitted.

Until you include a header written by someone with the same opinion, and now you get compile errors because they both defined 'u8'. I gotta be honest, all of those style suggestions look good until you try them in a non-solo and non-isolated project, and then you see what a mess you created. We've all been there, as C programmers, and we've all done that in the past, which is why we don't do it anymore

Unless they were defined to completely different types, that shouldn’t be an error

> Unless they were defined to completely different types, that shouldn’t be an error

In this case it almost certainly will be - after all, the blog posts `byte` is defined as char, which could be signed or unsigned. A correct typedef for `byte` is `uint8_t`, so it's almost guaranteed that this will conflict.

Which is why I said it's best not to redefine the primitive types - you're almost certain to conflict with someone else who defined it differently.

Re: My personal C coding style as of late 2023

#437

Earlier quoted context omitted.

Isn't "int" 64-bit on some (rare) architectures?

My computer being one of those (rare?) architectures. Though I think it is not entirely dependent on the processor and the OS choice also affects this.

What machine are you using?

Re: My personal C coding style as of late 2023

#438

Earlier quoted context omitted.

This is all very good and very, ahem, true. But (and it's a big butt); if (need_free == true) Is such a horrible code smell to me. You have a perfectly good boolean. Why compare it to a second boolean to get a third boolean? if (need_free) or if (!need_free) for the opposite case is so much better. I will admit that in my world this leaves if (need_free == some_other_bool) as something I don't have a particularly com…

Couldn't we do it like (!need_free == !some_other_bool)?

Clever, I like it.

Re: My personal C coding style as of late 2023

#439
post #421

Earlier quoted context omitted.

> Like, using u8 or i32 instead of the standard uint8_t or int32_t might save a few keystrokes [...] It is not about saving keystrokes, it is about reducing sensory load when reading it. Sorry, I know it may sound like I'm splitting hairs, but every single time when the argument of verbosity vs conciseness in programing languages comes around, this "keystrokes" argument is thrown and it is extremely flawed. The core…

I think you completely missed the point of his comment. C isn't a new programming language. There are well worn conventions and making custom types because you don't like them is like forking your own custom dialect nobody can understand for very little benefit.

No experienced C programmer is going to misunderstand u8 in a declaration.

Re: My personal C coding style as of late 2023

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

[deleted]
Post reply on HN