Live data from Hacker News

Lesser known tricks, quirks and features of C

blog.joren.ga

161–170 of 189 posts

Re: Lesser known tricks, quirks and features of C

#161
post #36
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!

Thanks! This prompted me to look up the flag to enable this. For GCC it’s: -Werror=format-security

The flag is -Wformat-nonliteral or -Wformat=2. -Wformat-security only includes a weaker variant that will warn if you pass a variable and no arguments to printf.

Re: Lesser known tricks, quirks and features of C

#162
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.

The former is ideally resolved with attribute((format_arg)), the latter with attribute((format)).

Re: Lesser known tricks, quirks and features of C

#163
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.

> One reason is locale-dependent format strings which are loaded from resource files. Aren't those usually resolved to string literals by preprocessor such that the compiler still could emit a warning?

Since the locale is only determined at runtime, and might even change at runtime, the format strings are usually dynamically loaded from text files, and are not in the form of string literals seen by the compiler.

Re: Lesser known tricks, quirks and features of C

#164

> 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.

_Atomic is indeed the correct qualifier to use for unsynchronized cross-thread access. The volatile qualifier doesn't add anything useful on top of that. Really, the only things volatile should be used for are MMIO, debugging, performance testing, and certain situations with signal handlers or setjmp within a single thread.

Re: Lesser known tricks, quirks and features of C

#165

Earlier quoted context omitted.

Strictly speaking there are essentially no programming languages that are even theoretically Turing-complete because they can only address a bounded amount of memory. For example, in C `sizeof(void*)` must be a well-defined, finite integer. But that definition is not useful in practical use.

There are plenty of Turing complete languages. For example JavaScript is Turing complete.

Even if that was true, any definition of Turing completeness that includes JavaScript and excludes C is worse than useless in practice. It's useless for communication, it's useless for education, it's useless for reasoning about capabilities. There's simply no place for such a definition in a civilized society.

Re: Lesser known tricks, quirks and features of C

#166

Earlier quoted context omitted.

Professional C developers definitely should be using at least designated init and FAM, standard features both added in C99 and currently 24 years old.

Well, it’s either a lesser known trick or it’s something people should be using. In general using lesser known tricks it’s not a good idea for production code. But I understand there are cases where there is no good alternative, so it’s warranted.

I mean, I titled the article "Lesser known trick, quirks and features of C". Not to mention the very first sentence:

> There are some tricks, quirks and features (some quite fundamental to the language!)

Re: Lesser known tricks, quirks and features of C

#167

Earlier quoted context omitted.

There are plenty of Turing complete languages. For example JavaScript is Turing complete.

Even if that was true, any definition of Turing completeness that includes JavaScript and excludes C is worse than useless in practice. It's useless for communication, it's useless for education, it's useless for reasoning about capabilities. There's simply no place for such a definition in a civilized society.

Turing machines themselves are a useless concept in our society. Since C is lower level and tied more to the physical hardware it makes sense that it is not Turing complete because Turing machines are not applicable to the real world. Computers do not work anything like an infinite tape. I've never seen a practical program have to implement a Turing machine.

Re: Lesser known tricks, quirks and features of C

#168
post #123

Earlier quoted context omitted.

> 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.

It is specified by POSIX, but not by ISO C (or C++). So most Unix(-like) systems support it. But the printf in Microsoft's C runtime doesn't. However, Microsoft does define an alternative printf function which does, printf_p, so `#define printf printf_p` will get past that. I think the real reason you rarely see it, is it is only used with internationalisation–the idea being if you translate the format string, the tr…

printf_p is pretty neat, thanks for the pointer. But I would bet that you will still find at least one %d gets turned into a %s.

I like printf format strings, but as a way of handling localizable strings I don't think they are the best.

Re: Lesser known tricks, quirks and features of C

#169

Earlier quoted context omitted.

The unary complement operator should get you there: unsigned int x = 0; const unsigned int max = ~x; while (x Or, #include const unsigned int max = UINT_MAX;

This is equivalent to while (1) { calc(x++); } which is an infinite loop, since the expression x is always true

Heh! Good catch! That is what I get for not testing. After UINT_MAX, x wraps around to 0.

Re: Lesser known tricks, quirks and features of C

#170

Compound Literals in C are great. They're no surprise to anyone coming from more sophisticated languages, but I've never seen them used in the C codebases I've worked on. What with C also allowing structures as return values, another rarely-used feature, they're really useful for allowing a richer API than the historical `int foo(...)` that so many people are used to seeing. C has so much legacy that it's really hard…

For many, I think "C" is still "C89."

I remember working on a commercial project in the mid-2000's that still had #ifdefs for K&R C prototypes (meaning, pre-ANSI C.) This was a recent-ish project at the time, started in 2000. Were people going to go back in time and compile it on an old architecture? I doubt it.

C moves slow.

Post reply on HN