A bizarre world of “type qualifiers on array parameters” in C
Have you stumbled upon some type qualifiers (e.g., const, volatile, or restrict) inside square brackets in C? It’s uncommon to see them…
A bizarre world of “type qualifiers on array parameters” in C
Have you stumbled upon some type qualifiers (e.g., const, volatile, or restrict) inside square brackets in C? It’s uncommon to see them there, but if you look into some C libraries or Linux man-pages, you may stumble upon them occasionally. I saw it today when I had to look up the definition of memccpy() from the standard C library, where the prototype of this function was like this:
void *memccpy(void dest[restrict .n], const void src[restrict .n],
int c, size_t n);
Let’s not pay attention to the fact that the parameter n is used as the length of the array parameter dest and src, and there is a dot (.) before the array size n. ( Brief explanation at the bottom.) What is restrict hanging around inside* the square brackets? Isn’t restrict a type qualifier? Are type qualifiers allowed inside square brackets? If so, what is the purpose?
First of all, what the hell is restrict?
The type qualifier restrict itself may not be your everyday C keyword that you routinely utilize and benefit from, yet I think its benefit is quite significant if you use it right. It’s not a functional keyword that you have to use to get something to work, but rather an optimization keyword (dare I say - it’s my understanding) that hints to your compiler that “the object that this pointer points to won’t be modified by other pointers during the lifetime of this pointer.” There are good examples of this keyword online (e.g., this Wikipedia page), so I’m not going to go deep into this keyword (gotta admit, I’m also not super familiar with this keyword, so if I go too deep, there’s a non-trivial chance that I’m spreading false information). But the gist of this keyword is that it enables your compiler to do more aggressive optimizations because there is no risk of the underlying object getting modified by others; the modifications done by this pointer are the only modifications done to the object, so it’s safe to assume that the value written in the object stays the same until the next write through this pointer.
Anyway, now we get the hang of restrict, let’s deal with the real meat; what’s restrict inside square brackets?
What’s restrict inside square brackets?
We can generalize this question to the “type qualifiers inside square brackets,” where the type qualifiers are the keywords that specify the properties of the data type. restrict is one such thing, and other keywords include const (“This data is constant”) and volatile (“This data can change anytime, like raw data from hardware sensors”). The type qualifiers usually appears next to data types (hence its name) because it’s supposed to qualify data types. So it’s not strange to see them around data types, even though some qualifiers may not be your everyday keywords.
But we’re talking about them appearing inside square brackets, where you usually expect the length of arrays there (in array definitions). My first guess was they may be the type qualifiers of individual elements, but it turns out that they are the type qualifiers of the array itself, not the elements. Now, what does it mean?
First, you should understand that the arrays in C are just pointers, annotated with a length. There are subtle differences between arrays and pointers, but the low-level implementation is the same: they point to the object in the memory. Now, this may ring a bell to you because if arrays are practically pointers, they can also benefit from the keyword restrict. In this case, the restrict arrays mean others won’t change the array's contents.
So let’s think about it. Can you restrict arrays by putting the keyword in conventional positions? The “conventional” position of the data type for arrays is the left-most part of the array declaration, but you need to understand that it is supposed to be the data type of array elements, not arrays themselves. So, if we have this function prototype:
int foo(const int aaa[30]);
the parameter aaa is the “array of 30 constant integers.” There is an interesting online article about reading out data types in C (Link), which is fairly convoluted, but this also ultimately says the same thing for array data types.
Now, we don’t want to restrict array elements; it’s the array itself that we want to restrict. How can you do this? Well, apparently, before C99, you couldn’t. According to my brief internet search, however, you could achieve what you wanted with restrict by declaring array parameters with pointers (remember arrays are practically pointers?). So, if we have this function prototype,
int bar(int * restrict bbb);
the parameter bbb is a restricted integer pointer that you’ll use as an array. No syntax clarifies your intent here (“bbb is an array”), but it’s the same thing in terms of effect.
But this is only about effect; how should future coders look at this code and recognize that bbb is an array? It’s usually not too necessary, of course, and if it’s necessary, you may also leave a little comment above the prototype that says “bbb is treated as an array.” This may work, but I think that resorting to a comment (=outside the language’s syntax) for such a fundamental detail is not so neat.
And apparently, the C99 committee also thought the same way. They tried to enable restricting arrays with simple syntax, and they chose inside the square brackets to denote the type qualifiers for an array. (Link) So, if we have this function prototype in C99,
int baz(int ccc[restrict 30]);
the parameter ccc is the “restricted array of 30 integers.” Mmm…
My two cents about the syntax.
So, I get it. The rationale for this slightly unusual syntax would be: arrays also need restrict just like pointers, and for that, C99 appointed that special place inside square brackets to declare restrict for arrays. This decision is actually quite reasonable because, conceptually, different square brackets in multi-dimensional arrays (“array dimension” in technical terms) may represent different pointers. If we stick to the concept that some type qualifiers like restrict were initially meant for pointers, multiple pointers inside multi-dimensional arrays may as well have separate type qualifiers. For example, in this function prototype:
int zoo(int ddd[restrict 30][50]);
only the first pair of square brackets (=the 0th dimension) will be restrict ed (i.e., the 1st dimension array like ddd[10] won’t be restricted). If we have to assign restrict to different square brackets, the position inside them would be the most fitting.
However, I still think that this syntax is somewhat awkward because my common sense says the thing inside square brackets is supposed to be the array length (in the array definition). The fact that I couldn’t deduce the “purpose” of the inside-square-bracket type qualifiers (and I wasn’t the only one) suggests that the syntax wasn’t so intuitive. Couldn’t we have dedicated the space between square brackets for array lengths? How about this syntax that I made up?
// THIS IS TOTALLY MADE UP. DON'T TRY THIS.
int hahaha(int eee((restrict)[30])[50]);
I just tried to reuse the common idiom of C syntax here: enclosing restrict with parentheses like how we write date types in type casting, and further enclosing them with other parentheses to limit the scope of this type (e.g., up to [30]). I admit, it’s slightly more verbose. But I think at least we can make our intention clear while not breaking the common sense about inside square brackets. There are online discussions on this syntax, too, although they’re mostly about “what they are” rather than “what it could have been.” (Link)
- C99 supports Variable-length Array (VLA) parameters, where you can feed the length of an array parameter with another parameter. But I guess this prototype of
memccpy()shown above is for documentation purposes because the size parameternwas defined after being used in the array parametersdestorsrc. Plus, as I know, the dot (.) before the array lengthnis the standard way in Linux manpages to denote references to another parameter in the prototype, which is not the actual part of implementation.
메타데이터
- post_id
- e930faa36150
- slug
- a-bizarre-world-of-type-qualifiers-on-array-parameters-in-c-e930faa36150
- url
- https://medium.com/@gwangmu/a-bizarre-world-of-type-qualifiers-on-array-parameters-in-c-e930faa36150
- canonical_url
- https://medium.com/@gwangmu/a-bizarre-world-of-type-qualifiers-on-array-parameters-in-c-e930faa36150
- author_url
- https://medium.com/@gwangmu
- status
- ok
- fetched_at
- 2026-06-29 01:02:39