Pointers in C, Part VI: Faking ‘restrict’

Pointers in C

“”But then acting is all about faking. We’re all very good at faking things that we have no competence with.”
— John Cleese

As so often in life, people love to do the exact opposite of what you advise. In my previous post I claimed that the ‘restrict’ feature isn’t that all-important and guess what? I received questions on whether it was possible to achieve the (promised) effects of ‘restrict’ even if a particular C dialect doesn’t support it (in case you are using C++ or some C version predating C99, for example).

YES WE CAN!

We just need to creatively combine the wisdom from the previous “Pointers in C” installments. In particular:

  1. Pointer access involving multiple pointers can be optimized if the pointers point to incompatible types.
  2. structs with different tag names constitute different, incompatible types, regardless of whether the struct members are identical or not.
  3. A pointer can be converted to a pointer to a different type as long as the resulting pointer is suitably aligned for the target type.
  4. A pointer to struct points to its initial member.

Do you ‘C’ it?

SPOILER ALERT!

Again, I use the ‘silly’ example to demonstrate the technique. The idea is to wrap the original types (‘int’) in structs with different tag names thus yielding different (incompatible) types:

Believe it or not — it works:

Why? To the compiler, the pointer types are different (item 2) and hence it doesn’t assume that they point to the same memory (item 1). Because of item 3 and 4 in the list above, the calling code can still pass plain ‘int’ arrays/pointers, just like in the original code. However, nasty casts are required when calling ‘silly4’ from C++ code:

Contrary to C++, C is only weakly typed so such casts are not necessary officially, unless you want to get rid of compiler warnings, which you always want to, don’t you?

You could argue that these strange ‘struct int’ pointers that are used in the signature of ‘silly4’ kind of document the fact that the passed pointers are “restricted” and mustn’t overlap. However, I prefer to keep the original ‘int*’ interface and hide this struct business from callers altogether:

The generated code is identical to the one derived from ‘silly4’.

I still stick with my original recommendation that the ‘restrict’ feature is not that useful as it’s a legally binding contract for the caller while the compiler is free to ignore this plea for performance. If you want to use ‘restrict’ regardless of my advice, even if your compiler doesn’t support it, you now know how to emulate it in a portable fashion.

Pointers in C, Part V: The ‘restrict’ Qualifier

Pointers in C

“Le vrai est trop simple, il faut y arriver toujours par le compliqué.”
(“The truth is too simple: one must always get there by a complicated route.”)
― George Sand, Letter to Armand Barbès, 12 May 1867”

Exactly one year ago, I started this series on pointers, but what I really wanted to blog about originally was a rather arcane and rarely used keyword that first appeared in the C99 language standard: the ‘restrict’ qualifier. But after trying to digest the formal definition in chapter 6.7.3.1 I decided that taking a little detour would make my and my reader’s life much easier.

Let me set the stage for ‘restrict’ by summarizing what I wrote in episode 3 about the “strict aliasing rule”:

1. The compiler might optimize code involving multiple pointers, provided the pointers are not aliased; that is, they don’t point to the same object or memory.

2. The compiler assumes that pointers to incompatible types never alias.

3. The compiler assumes that pointers to compatible types (same types, apart from CV-qualification and signedness) potentially alias.

Therefore, a function with this signature is eligible for compiler optimization:

whereas this one is not:

This is unfortunate, because most likely, the arrays passed to the second version of ‘transform’ are in completely different, non-overlapping memory regions. But the compiler doesn’t know and hence stubbornly adheres to the strict aliasing rule.

The ‘restrict’ qualifier, which — contrary to the ‘const’ and ‘volatile’ qualifiers — can only be applied to pointers, is a promise given by the programmer to the compiler that pointers don’t alias even though they point to objects of the same type. Therefore, this version of ‘transform’ can be optimized by the compiler:

Let’s put this to the test with the ‘silly’ example from episode 3:

Before knowing about the strict aliasing rule, we were surprised to see that the memory access to ‘x’ in the return statement was not replaced with a simple ‘return 0’. After having learned about the strict alias rule, it’s clear: since ‘x and ‘y’ point to the same type, the compiler must assume that they may point to the same memory location and hence it loads the value pointed to by ‘x’ from memory afresh:

Now, if we tell the compiler that ‘x’ and ‘y’ never point to the same memory location, optimization is possible:

Nice, isn’t it?

If you use the ‘restrict’ qualifier on a pointer, you promise that — at least for the lifetime of the restricted pointer — the object pointed to is only accessed through this pointer. Break that promise and you get undefined behavior. (In the ‘silly3’ example, the lifetime of the pointers ‘x’ and ‘y’ end once the call to ‘silly3’ returns.)

In the C99 language standard, many functions from the standard library have been revised and now make use of the ‘restrict’ keyword. Take ‘memcpy’, for instance:

As everybody knows, ‘memcpy’ can only copy non-overlapping blocks of memory and this fact is nicely highlighted by the use of the ‘restrict’ keyword: during the call to ‘memcpy’ the memory regions src[0] to src[n] as well as dst[0] to dst[n] are exclusively owned and may not be accessed by other pointers. Since ‘memmove’ can copy overlapping blocks of memory (with a little speed penalty, of course), ‘memmove’ consequently doesn’t declare restricted pointers:

Please be aware that ‘restrict’ is not supported by the C++ language standard and it’s unclear whether it ever will be. If you mix C99 and C++ code, you might have to strip the ‘restrict’ keyword from C99 headers to avoid compilation errors:

In general, I’m not a big fan of optimization features that the compiler is free to ignore. If utmost performance is important, you want dependable performance. Most likely, your routine is not on the performance critical path, anyway. If you think it is, carefully profile your code and after you proved that it is, you’d better code that part in assembly language. Without such evidence, sprinkling your code with ‘restrict’ is little short of premature optimization. (I complained here about the unnecessarily overused ‘inline’ keyword for the same reason.)

What I do like about the ‘restrict’ keyword, though, is that by unraveling it, we’ve made a beautiful journey through important everyday programming topics like “pointers vs. arrays”, “type qualifiers”, “pointer conversion rules”, and the “strict aliasing rule”. The journey was the destination.

Boolean Arguments are BOOL-Shit

“All generalizations are false, including this one.”
— Mark Twain

In programming, little is as obscure as code that passes boolean literals to functions.

As an example, consider the following invocation of a method that sets logging options on a logger object:

What does this really mean? Even looking at the declaration of ‘setOutputControlMode’ doesn’t give a satisfying answer:

You need to delve into the implementation of the ‘Logger’ class to really see the intent:

There you go! After calling ‘setOutputControlMode’ with ‘true’ as the first argument, subsequent logging will additionally go to ‘stderr’; passing ‘true’ as second argument will automatically append a newline character after every log statement.

While you could argue that the wishy-washy name of method ‘setOutputControlMode’ was badly chosen, it was probably done so to accommodate even more options in the future. I’m convinced that sooner or later another boolean parameter will pop up — ‘buffered’, to specify whether logging should be buffered or not.

How should you deal with such obviously inferior interfaces? The strategy depends on whether you own the offending code or not. Let’s start with the first case, where you’re using some 3rd party library that you can’t directly modify.

HIDING THE DIRT

First of all, make it a habit to never feed these boolean monsters with boolean literals. Don’t even do this if the method is part of a standard library, like Java’s ‘Component.setVisible(boolean b)’ method. Stand your ground and shame the original author by working around it. But how?

One easy solution is to define a couple of boolean constants in your code:

At the expense of a little bit more typing, code that calls ‘setOutputControlMode’ becomes much more expressive:

The only risk that’s not mitigated is that one can still confuse the order of arguments. After all, the compiler will happily accept this slip:

Which is, of course, not what the developer had in mind.

A safer approach is to use wrapper functions. This is particularly useful if you don’t need all flag combinations in practice. Let’s assume you always want to emit newlines at the end of every log entry and only sometimes want to enable/disable echo to ‘stderr’. All you need to do is define two straightforward helper functions in your own code base:

Using these wrapper functions is both, highly readable and safe:

AVOIDING THE DIRT

If you can modify the source code, you have even better options. Let’s assume that a colleague of yours developed a GUI framework that has the same weakness as Java’s java.awt.Component class; that is, it provides a method which takes a boolean argument:

Now, there’s probably tons of code that uses this method, as ugly as it may be. In order to maintain backwards compatibility, I would designate ‘setVisible’ as deprecated and add two wrapper functions to your colleague’s class which clearly communicate their intend:

If backwards compatibility is not an issue or if you’re designing a completely new method, you should do it the right way, and the right way is to use enums instead of booleans:

In exchange for roughly one additional minute of work for the developer, everyone gets a readable interface:

It’s a given fact of programming, that when there are two states or modes, it won’t be long until a third one pops up. No problem, if you used enum parameters from the outset:

In the visibility example, we have mutually exclusive modes. In the ‘setOutputControlMode’ example, however, options can be combined. Still, enums are a pragmatic solution:

Notice that I added the suffix ‘FLAGS’ as a hint to the reader that these options can be freely mixed with the binary OR operator:

This, of course, only works in plain C. A C++ compiler will complain that the integer result that operator ‘|’ yields cannot be converted back to an enum type, so in order to please your C++ compiler you have to apply a ‘static_cast’:

Such casts are never pretty, but when they get the job done, they’re acceptable.

Let me bring this post to a close by driving home the following guidelines:

1. Never pass boolean literals (‘true’/’false’) to functions. Define meaningful symbolic constants instead.

2. Alternatively, consider writing wrappers around functions taking boolean arguments. Remember that the best (most readable) functions take zero arguments:

“The ideal numbers of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification ‐ and then shouldn’t be used anyway.”
— Uncle Bob (“Clean Code”)

3. If you are the author of a method that takes options, spend the effort and code dedicated, niladic setters. If that doesn’t feel right, use enum parameters. But on no account should you ever resort to boolean arguments.

BBC micro:bit —The End of All Excuses for Not Learning Programming

“He that is good for making excuses is seldom good for anything else”
— Benjamin Franklin

The BBC micro:bit, or Micro Bit, is a small embedded computer designed by the BBC for use in computer education in the UK. Every British schoolchild of grade 6 – 8 gets a Micro Bit for free. But before you become too envious: You can buy one for about 18 EUR—just do an Internet search to find a local dealer.

In my view, the Micro Bit is an excellent platform for learning programming since it sports many attractive features, such as:

– 5 x 5 LED matrix display
– Temperature sensor
– Ambient light sensor
– Accelerometer
– Magnetometer/compass
– Bluetooth connectivity
– Input buttons
– Various GPIO ports to attach sensors/actuators
– Audio output jack

But the coolest thing about it is that it comes without friction. The development environment is available online, which means that you can do all your programming in your favorite web browser—no need to install any software or drivers. The Micro Bit presents itself as a USB mass storage device onto which you just drag & drop your executable files.

COMMON EXCUSES

Let me show you more of the Micro Bit’s features by dispelling some common excuses for not starting to write code for it today:

Excuse: I don’t possess a Micro Bit!
Response: You don’t need one. There’s a powerful simulator directly on the Block Editor coding environment. I highly recommend starting out with the Block Editor, anyway. Try it out now, before reading on! (Let’s put it this way: If I recommend something provided by Microsoft, it must really mean something, right?)

Excuse: I have no idea what to code.
Response: There are dozens of step-by-step tutorials and pre-built examples on the Block Editor page. Just click on “Projects” and then again “Projects” or “Examples.”

Excuse: Graphical programming sucks and is only for wimps.
Response: While I’m a big fan of text-based programming languages, I think it’s a good idea to toy around with the Block Editor for a while, just to familiarize yourself with Micro Bit’s features. Once you’ve learned what it’s capable of, you can do the rest of your programming in JavaScript or Python.

Excuse: I am (or want to become) a hardcore embedded coder and I’m not interested in high-level, wimpy JavaScript and Python programming.
Response: The Micro Bit is based on ARM’s Mbed IoT platform. There’s an online IDE on Mbed’s website that allows you to program your Micro Bit in C/C++, if you want.

Excuse: I live in a cabin in the woods and have poor Internet connectivity. Online programming is not an option.
Response: Once you’ve visited the Block Editor, you can access it from your browser even if there’s no Internet connection. But since you’re living in a cabin in the woods, you are probably a hardcore C/C++ coder, aren’t you? Well, thanks to the Yotta build system from Mbed, you can do command-line based builds and write your code in Emacs or vi, just as you please.

Excuse: I don’t have time.
Response: This is a lame excuse and I truly detest it. We’re all busy yet have plenty of time for things that are important to us. When we say, “I don’t have time,” we are really saying, “I’m a lazy bum and such a coward that I don’t dare confessing it to you.” Don’t get me wrong: It’s completely OK if you don’t like programming and have other priorities in life, but if you read my blog and you’ve made it this far, you should at least give it a quick try so that you can make an informed decision.

PLAYFUL TESTING

The Micro Bit does look like the perfect learning platform, doesn’t it?

In fact, there’s only one thing I wasn’t so happy about, at least initially: As far as I know, you can only use the simulator if you code in the Block Editor or JavaScript. My preferred Micro Bit language, however, is Python.

I scratched my head a bit and came to the conclusion that this was not really a problem, after all. Why? A simulator basically means manual testing, and manual testing isn’t really something we should ever aim for—it’s no fun at all. Instead, I want to use automated unit tests to ensure that my code behaves correctly even after the most minute change.

But there’s a catch: If you want to run Python unit tests on a host PC (not on the real Micro Bit device) you have a problem. Naturally, the ‘microbit‘ package, which provides access to the Micro Bit’s runtime and it’s peripherals, isn’t part of the standard Python distribution.

As a remedy, I set out to create a little Micro Bit playground, one that comes with a ‘microbit’ package containing mock objects for all the API objects that the original ‘microbit’ package offers. Here’s the essence of the ‘happy_sad’ example contained in the playground GitHub repository:

And here are the corresponding test cases using the mocked microbit.py module:

Just run ‘make’ to execute the test cases and ‘make install’ to transfer the code to your plugged-in Micro Bit. It can’t get any more convenient. No more excuses left!

Pointers in C, Part IV: Pointer Conversion Rules

Pointers in C

“Failure is the key to success; each mistake teaches us something.
— Morihei Ueshiba

Sometimes, someone walks up to you and claims that there is a bug in your well-crafted code. Then, after having successfully proved that individual wrong, it occurs to you that there is indeed a bug—albeit a different one! Those are quite humbling experiences, but experiences that we should be most grateful for.

SETTING THE STAGE

This episode was triggered by feedback that I received from a reader regarding a “Dangerously Confusing Interfaces” post. In said post, I advise that instead of accepting a pointer to “uncopied” memory like this:

‘WriteAsync’ should rather take a pointer to an opaque data structure named ‘uncopied_memory’:

“uncopied” memory means that for the sake of efficiency, the called function doesn’t copy the provided data but instead expects you to keep it alive and unchanged while the called function is executed asynchronously. Since the suggested interface change requires an explicit cast to an ‘uncopied_memory’ pointer, it’s a lot less likely that a temporary buffer allocated from the stack is passed accidentally. The idea of the proposed approach is that every call to ‘WriteAsync’ requires an explicit cast that acts as a reminder to the programmer that the buffer’s contents must be preserved.

For instance, if you wanted to pass a structure that I used in the previous installment of this series to ‘WriteAsync’, you would do it like this:

But back to the question. What the reader was worried about is that since ‘measurements_t’ and ‘uncopied_memory’ are by no means compatible, wouldn’t a cast to an ‘uncopied_memory’ pointer constitute a violation of the “strict aliasing rule“?

Actually, when it comes to the “strict aliasing rule,” the fact that these structs have incompatible members doesn’t really matter—even if you accessed the stored value through a pointer to a struct with an identical set of members you would be in trouble; if the tag names of the structs are different, it already counts as a violation of the “strict aliasing rule.”

The key word here is access. If you just create a pointer to incompatible types, everything is fine. Within ‘WriteAsync’ you just cast the received ‘uncopied_memory’ pointer into a ‘uint8_t’ pointer and access the provided data byte-wise, which is always safe, as you know (if you didn’t know, go back and read my previous post).

So far, so good. We don’t access stored memory through incompatible pointers; we only do pointer conversion, which is always safe, isn’t it? I replied to my reader that everything was fine, there was no violation of the “strict aliasing rule.”

Nevertheless, I couldn’t rid myself of this nagging feeling about whether the conversion/cast is really always safe.

POINTER CONVERSION RULES

The venerable book “The C Programming Language” by Brian Kernighan and Dennies Ritchie has this to say on pointer conversions:

A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage. It is guaranteed that a pointer to an object may be converted to a pointer to an object whose type requires less or equally strict storage alignment and back again without change; the notion of alignment” is implementation-dependent, but objects of the char types have least strict alignment requirements. As described in Par.A.6.8, a pointer may also be converted to type void * and back again without change.

Let me paraphrase: pointer conversion is safe provided the alignment requirements of the target type are less or equal to the alignment requirements of the source type. The converted pointer can be converted back to the original pointer without problems.

Though, the statement “The resulting pointer may cause addressing exceptions” is not clear to me. What does it mean? If the target type has stricter alignment requirements, do you get “addressing exceptions” when you create the pointer or when you access memory through it? Let’s assume that we are on a typical platform where objects of type ‘double’ are aligned on an 8-byte boundary and ‘chars’ have no alignment requirements (‘chars’ are aligned on a 1-byte boundary, so to speak.):

The conversion (1) is 100% safe and so is the corresponding read-access (2): the alignment requirements of type ‘char’ are less than the alignment requirements of type ‘double’. (4) is 100% unsafe, but what about (3)? Aren’t we just creating a pointer? To find out, I had to dig deep into my copy of the C99 language standard. Eventually, I found what I call the “pointer conversion rule”:

6.3.2.3/7 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object.

There you have it and much more precise than the paragraph from “The C Programming Language.” Believe it or not—statement (3), the sheer pointer conversion already gets you into the realm of undefined behavior. Who knew?

So what does this mean regarding the conversion/cast from a ‘measurements_t’ pointer to an ‘uncopied_memory’ pointer? As we know from the standard, it would be safe if the alignment requirements for ‘uncopied_memory’ were less or equal to the alignment requirements of ‘measurements_t’.

In the previous example, we had to deal with primitive types (‘char’, ‘double’) whose alignment requirements can easily be determined. In order to find out about the alignment requirements for structs, we need to dive once more into the C99 standard document:

6.7.2.1/13 A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

Meditate on this for a while. Paraphrased, this all means that the alignment requirements of a struct are the same as the alignment requirements of a struct’s first member. So the question boils down to this: Are the alignment requirements of a ‘void’ pointer (‘uncopied_memory’s first member) less or equal to the alignment requirements of a ‘char’ (‘measurements_t’s first member)?

Of course, they’re not! A pointer type (like void*) is more or less just an integer type in disguise that is capable of holding all the addresses of your system and as such, pointer types have the same alignment requirements as regular integer types. On a 32-bit platform, pointers typically comprise 4 bytes. Thus, on typical 32-bit platforms, they will need to be aligned on 4-byte boundaries.

By contrast, a character (like the first element of measurements_t) comprises exactly one byte and thus has no alignment requirement—it can be stored at any address in memory.

Since the alignment requirements of the first element of ‘uncopied_memory’ are stronger than the alignment requirements of ‘measurements_t’, we can conclude that my advice to cast to ‘uncopied_memory’ may yield undefined behavior. Not because of the “strict aliasing rule,” but because of a violation of the “pointer conversion rules.”

To solve the problem, the type of the ‘dummy’ member of ‘uncopied_memory’ needs to be changed to ‘char’, a type that has the weakest alignment requirements. I have updated the “Dangerously Confusing Interfaces” post accordingly.

Yet Another Software Metaphor: Pitoning

“Gravity wins over all other known forces”
— Andrea M. Ghez

As software developers, we have to deal with conflicting goals on a daily basis. One example is finding an answer to the question whether to hack out new features or clean up existing code. Or, in slightly more professional words: shall we make progress in terms of functionality or in terms of quality?

THE PROBLEM

Non-technical/business people usually don’t understand the importance of software quality and tend to err on the side of rapid feature development—they assume that by focusing on features, they can sell their product sooner. Software developers by and large do understand the importance of software quality but usually also err on the side of feature development. Why? Because it’s much more fun to work on something new than doing mundane quality improvements.

As a result, many projects focus almost exclusively on churning out features. What these teams often fail to realize is that not only are features progressing rapidly—the overall risk is progressing rapidly as well.

In projects that opt for such a “code-and-fix” model, software entropy (some prefer the term technical debt) will constantly increase and even if these projects get finished one day (which is really not that certain) the messy code base might not be strong enough to support the features required for the next major release. Even worse, nobody is able to understand and maintain the messy code apart from the original authors, who have probably left the company in the meantime, anyway.

SOFTWARE METAPHORS

Software quality is yet another term for investment protection. It ensures the money that went into a project is properly insured. For all but the small, short-lived projects such insurance is crucial for the long-term success of any company.

Metaphors and analogies like “investment protection” and “technical debt” have quite a history in software development. For decades we have talked about “building software,” “software architecture,” “bugs,” and rightly so: by comparing something we are not familiar with to something we understand well, we can gain insights that help us understand the unfamiliar topic.

PITONING

Recently, I had an idea for yet another software-related metaphor, which I call “Pitoning.” Pitoning compares software development to rock climbing, and it helps in finding trade-offs between feature progress and quality.

With the exception of free solo climbers, rock climbers don’t rush to the summit without breaks. Doing so would be extremely fast, but also highly risky—even a minor slip could be fatal. Instead, after they have made some progress, sane rock climbers will drive a piton into the rock and hook into it before climbing on. This “pitoning step” costs some time, of course, but it increases the probability that climbers will make it safely to the top significantly.

When we set out to develop a feature, we typically don’t know what’s the best design, so we experiment and try out different approaches. During this exploratory phase, we don’t want to waste time making the code as beautiful as possible, since it might be replaced by something else, eventually. However, once we have a working solution, we do the pitoning; that is, we add missing unit tests, we refactor, we make the code robust and in general industrial-strength, which may sometimes even include drawing UML diagrams and writing documentation.

CONCLUSION

The key concept behind pitoning is that a) experimentation and learning are not just good but essential and b) cleanup is done immediately after a working solution has been implemented—not at “some” point in the future. In certain cases, the pitoning phase will be longer than the exploratory phase. But skipping pitoning is not an option—gravity will surely get us. Many products and even whole companies have gone bust because of product recalls and lost reputation.