extern "C" static array function parameter

extern "C" indicates to the C++ compiler that the function name should not be mangled. Since you're linking against an external library, the expectation is that the external library has a function (and only one function) called foo. The static keyword in C99 and onward in an array size tells the compiler that "this array will be at least this size", which may allow the compiler to make certain optimizations (I don't know what optimizations these could be, but consider that it could possibly do loop unrolling up to N = 4, where you declared void foo(int i[static 5]); If you pass an array that is not at LEAST this size, you could have a bad time.

The immediate solution is just that we need to tell the C++ compiler:

  1. There is a function called foo
  2. It takes an int * as a parameter
extern "C"
{
    void foo(int i[]);
}

But we lose the information to anyone using this in the C++ program that this function MUST be at least size N (which is what the static keyword in the array size meant). I can't think of a good way to force a compile-time check on this except possibly through some type templated wrapper function:

#include <cstddef>

extern "C"
{
    void foo(int i[]);
}

template <std::size_t N>
void c_foo(int i[N])
{
    static_assert(N >= 5);
    foo(i);
}

int main(int argc, char** argv)
{
    int a[5] = {1, 2, 3, 4, 5};
    int b[4] = {1, 2, 3, 4};

    c_foo<5>(a); // this will be fine
    c_foo<4>(b); // this will raise a compile-time error
}


To be extra safe, I'd put the function prototypes for your c_foo functions and any "safe" extern "C" prototypes in one c_library_interface.h file, and the function definitions for your c_foo functions and any "unsafe" extern "C" prototypes in another c_library_interface_unsafe.cpp file. That way, as long as you don't include the unsafe file in your main C++ files, you should only be able to interface with the static array size functions through the templates, which will do some size checking.


(This is additional information to the answer by John)

The C header is not correct in C++ so you will have to modify it .

Probably the intent of [static 1] is to indicate that the function should not be called with a null pointer. There's no standard way to indicate this in both languages and the author's choice is not compatible with C++.

Some major compilers support __attribute__((nonnull)) in both languages, either as a postfix to each parameter, or as a prefix to the function which then applies to all pointer parameters.

In my personalized header I define a preprocessor macro that expands to the equivalent syntax for each compiler , or blank for compilers that don't support it.

Bear in mind that there's no requirement for a compiler to enforce the behaviour and there will certainly be cases where it doesn't (e.g. passing on a received pointer that it doesn't know anything about).

So IMHO with the current state of compiler attitudes towards this feature (be it the attribute or the static 1) , this should be viewed as a form of user documentation.

I actually have decided not to use it in my own code, after some experimentation: using this attribute will cause the compiler to optimize out any null-pointer checks in the function body, which introduces the possibility of runtime errors since there is no effective prevention of null pointers being passed. To make the feature usable, the compiler would also have to issue diagnostics any time the function is called and the compiler cannot guarantee the argument is non-null. (Which is an option I would like to see in compilers, but so far as I know, doesn't exist yet).

Tags:

C++

C

C99

C11