Live data from Hacker News

Lesser known tricks, quirks and features of C

blog.joren.ga

121–130 of 189 posts

Re: Lesser known tricks, quirks and features of C

#121

Earlier quoted context omitted.

>The %n functionality also makes printf accidentally Turing-complete No it doesn't. Printf has no way to loop so it's not Turing complete. Even if you did what the IOCCC entry did with putting it into a loop it still wouldn't be Turing complete as it would not have an infinite memory.

Nothing real is "Turing complete" if it requires infinite memory. That's a property only abstract machines can have. In common parlance, something is Turing complete if it can compute arbitrary programs that can be computed with M bits of memory, where M is arbitrary but finite.

So in common parlance finite state automata are Turing complete? That definition doesn't make any sense.

Re: Lesser known tricks, quirks and features of C

#122
post #75

Earlier quoted context omitted.

Why are these not compiler errors by default? Opting in to such important safety features seems like broken design.

One reason is locale-dependent format strings which are loaded from resource files. Also, in personal projects, I almost always used custom wrapper functions for printf/fprintf/sprintf for various reasons, so that default wouldn’t be of much use, unless maybe I could enable it for the custom functions.

I've never seen locale-dependent format strings work well. The translators will change the formatting codes, and you can't change the order of the formatted arguments. You are much better off with some other mechanism for this.

(I have no recommendations. When I've seen this stuff done properly, on the occasions I've managed not to avoid doing it, it's always been using some in-house system.)

Re: Lesser known tricks, quirks and features of C

#123
post #122
post #75

Earlier quoted context omitted.

One reason is locale-dependent format strings which are loaded from resource files. Also, in personal projects, I almost always used custom wrapper functions for printf/fprintf/sprintf for various reasons, so that default wouldn’t be of much use, unless maybe I could enable it for the custom functions.

I've never seen locale-dependent format strings work well. The translators will change the formatting codes, and you can't change the order of the formatted arguments. You are much better off with some other mechanism for this. (I have no recommendations. When I've seen this stuff done properly, on the occasions I've managed not to avoid doing it, it's always been using some in-house system.)

> you can't change the order of the formatted arguments.

You can with the $ syntax. Never seen it used though. Maybe it isn't very portable.

Re: Lesser known tricks, quirks and features of C

#124
post #88

Earlier quoted context omitted.

Please don’t use C at all in production if you can help it.

So no Unix, Linux, Bash, cURL, Ruby, ...?

No Windows or OSX either (yes I know OSX is a Unix). Looking forward to all the RIIR people using Redox as their daily driver.

Re: Lesser known tricks, quirks and features of C

#125

I wish there was a language "between" assembly and C: basically assembly with some quality-of-life improvements. Shortcuts to reduce redundant chores (like those multiple instructions to load one 64-bit number into an ARM register) but minimal "magic" or unintended consequences as in C. Things like maybe a function call syntax like: CALL someFunc(R1: thingForRegister1, @R7: pushR7ThenPopOnReturn, R42: [memoryAddressF…

You just need a decent assembler with macro support. Here's a few lines of code I have for 32-bit x86 code:

    PRINTF "main_task: sf=%p",ebp
    PRINTF " sf: 1=%d 2=%d 3=%d 4=%d",dword [ebp+8],dword [ebp+12],eax,ebx
I'm using NASM and it wasn't hard to write the macro to do so.

Re: Lesser known tricks, quirks and features of C

#126

> The 0 width field tells that the following bit fields should be set on the next atomic entity (char). This isn't correct since int can't be less than 16-bits. Fields are placed on the nearest natural alignment for the target platform, which might not support unaligned access.

The entire placement of bitfields is implementation defined.

So yeah, the placement in memory might be `xxxxx000 00000000 yyyyyyy0` but it could also be `yyyyyyy0 00000000 xxxxx000` or `yyyyyyy0 00000000 00000000 xxxxx000` or anything else.

Bitfields are very misunderstood and really only safe to treat as an ADT with access through their named API, not their bit placement ABI. People misuse them a lot.

Re: Lesser known tricks, quirks and features of C

#127
post #35

Earlier quoted context omitted.

"format not a string literal" is one warning I always upgrade to an error. Dear reader: you should do this, too!

I don't like a lot of things in C++, but one thing worth praising in particular is std::format std::format specifically only works for constant† format strings. Not because they can't make it work with a dynamic format, std::vformat is exactly that, but most of the time you don't want and shouldn't use a dynamic format and the choice to refuse dynamic formats in std::format means fewer people are going to end up shoo…

Nice, I didn't know about https://wg21.link/P2216 .

Re: Lesser known tricks, quirks and features of C

#128
post #62

Earlier quoted context omitted.

I don't believe those are functionally / semantically equivalent - couldn't care less does imply a min() value of care. In contrast, the author is suggesting a comparative only. And, on careful re-reading, I suspect the author is having a play on syntax & semantics here -- the context of the quote is: > You may ask, since when C has such operator and the answer is: since never. --> is not an operator, but two separat…

Hah, unfortunately this bit of "poetry" wasn't intentional. I just meant that C does care about whitespace, just not a lot.

Ah apologies - I missed that subtlety. Unfortunately the whole 'could care less' debacle has left me somewhat triggerable.

'cares not so much' / 'doesn't care so much' might also work in your context.

Re: Lesser known tricks, quirks and features of C

#129
post #77

Earlier quoted context omitted.

I think the problem with this is the C compiler has to find a solution which work with all the architectures it is expected to support. It order to achieve this, it must generalize in some areas and have flexibility in others. C programmers are required to be familiar with both the specifics of the architectures they are building for and the idiosyncrasies of their complier. I always assumed most other compiled langu…

> Bitfields in C can be manageable. For the use case of specifying a more efficient representation of a fiction confined to the program, then no harm, no foul. But the use case of specifying a hardware- or network- or ABI-specified data layout, then you need those bits in exactly the right spot, and the compiler should have no freedom whatsoever. (I'm thinking of the case of network protocol packets and hardware memo…

This shouldn't be an issue unless you are attempting to have the bit field span across your type boundary. Bit fields by definition are constituents of a type. It doesn't restrict you from putting the bits where you want them but how you accomplish that. In this case, you'd either have to split the value across the boundary into two fields or use a combination of struct/unions to create an aliased bit field using a misaligned type (architecture permitting of course). You either sacrifice some convenience (split value) or some readability (union) but it is still reasonable.

The compiler itself is not taking a liberal approach to bit field management, it is only working within the restriction of the type (I am speaking for GCC here, I can't vouch for others). But if you think of them as an interface to store packed binary data freely without limitations I can understand why they seem frustrating. They are much more intuitive when you consider them as being restricted to the type.

Re: Lesser known tricks, quirks and features of C

#130

> volatile type qualifier > This qualifier tells the compiler that a variable may be accessed by other means than the current code (e.g. by code run in another thread or it's MMIO device), thus to not optimize away reads and writes to this resource. It's dangerous to mention cross-thread data access as a use case for volatile. In standard C, modifying any non-atomic value on one thread, while accessing it on another…

These days it can be chained with _Atomic to achieve the desired effect. That said, oftentimes you need more serious synchronization mechanisms your library would provide.
Post reply on HN