2

I've just encountered code in the project dcraw that's causing the Visual Studio 2012 compiler to fail. It's of the following form:

void CLASS cubic_spline (const int *x_, const int *y_, const int len)
{
  float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
  ...

The problem is the creation of these variable length arrays on the stack. I've never really seen code like this -- is it possible to compile this in the Visual Studio compiler?

10
  • 2
    dcdraw is written in c, not c++. c and c++ are two different languages with a similar syntax. Commented May 9, 2014 at 16:07
  • 2
    C++ does not support Variable Length Arrays except as compiler extensions (a la gcc). Commented May 9, 2014 at 16:07
  • I didn't realize variable length arrays were valid C and not C++. My mistake on mis-tagging the question as C++: it's not normally that important to distinguish between the languages, but in this case it appears to be! Commented May 9, 2014 at 16:19
  • 1
    @aardvarkk Do I have to guess what that error is? Is this some kind of puzzle? Commented May 9, 2014 at 17:13
  • 2
    The message is always relevant and I don't understand why you'd go out of your way to hide it from the authorities. You're the one with the question so you are not qualified to decide that some details don't help. Commented May 9, 2014 at 17:19

3 Answers 3

2

There are working compiler extensions (such as Clang's one and GCC's one) that allow this, but it's not standard, yet.

In C++11 you can also use constexpr if the numeric value is constant. And finally a proposal has been submitted to standardize it.

If x_ and y_ are meant to be arrays, you can just use std::array as follows:

template<std::size_t size>
void CLASS cubic_spline (std::array<int, size> const& x, std::array<int, size> const& y)
{
    using float_array = std::array<float, 2 * size>;
    std::array<float_array, 2 * size> A;
    float_array b, c, d;
    // ...
}

This way you could ensure that the passed arrays dimensions are equal, at compile time.

Otherwise you can clean that up with std::vector:

void CLASS cubic_spline (std::vector<int> const& x, std::vector<int> const& y)
{
    std::vector<std::vector<float>> A(2 * x.size());
    std::vector<float> b, c, d;
    // ...
}
Sign up to request clarification or add additional context in comments.

8 Comments

How would this code look were it to take advantage of the constexpr syntax?
@aardvarkk: constexpr would only work for compile-time computations, would it be alright with you ?
@aardvarkk, it's hard to say, because constexpr can't just be blindly used to replace const. For example you can't put constexpr as a function argument. What are x_ and y_ in your example?
The function is called twice in the code, once as cubic_spline(cx, cf, 9); and once as cubic_spline(cx, cf, 18);. In the first example, cx and cy are int[9] and in the second example they're int[18].
This is a question about C and variable length arrays are a standard core C99 feature. No need for extensions.
|
2

As mentioned, VLA (Variable-Length Arrays) are a C feature, and more to the point a C99 feature which Visual Studio does not support. On Linux, Clang and Gcc both support C99 (and C11 I believe) and allow this syntax in C++ as an extension.

In C++, you can easily transform the code by switching to std::vector<float> for all simple arrays. Only A will require a bit more work:

  • you can either use a std::vector< std::vector<float> >, but then you lose contiguity and locality
  • or you can use a flattened version std::vector<float> A(2*len*2*len); but then you will lose access by A[i][j] which will have to be transformed into A[i*2*len + j] instead

In any case, you will need to update this code to make it work on Visual Studio.

EDIT: per your comment:

The function is called twice in the code, once as cubic_spline(cx, cf, 9); and once as cubic_spline(cx, cf, 18);. In the first example, cx and cy are int[9] and in the second example they're int[18].

In this case you can actually make the function a template:

template <size_t len>
void CLASS cubic_spline(int const (&x)[len], int const (&y)[len]) {
    float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
}

Note that I removed the last parameter, because it is no longer necessary. The type of x and y is int const (&)[len] which is a reference to an array of int const of length len.

2 Comments

Very helpful post, thanks. I knew VS didn't support C99, so it answers the question quite directly to know that not only are VLAs a C feature, but specifically a C99 feature.
@aardvarkk: actually, if the dimensions are known at compile time, you can much more easily deal with the issue by just transforming the signature of cubic_spline to make it Standard C++. I've edited my answer to show off the power of references to array in function template :)
1

This is a GCC-specific compiler extension, see Arrays of Variable Length. I am not aware of any compiler options to make them work out of the box in VC. If this is a very isolated problem, try preprocessor #ifdefs to serve different code to VC.

5 Comments

Not true. VLA's are a C99 standard feature (and this question is tagged as C by OP).
@Danvil: I see it tagged as C++.
There is some kind of continuous editing... Anyway, dcraw is a C program.
I guess it should finally be re-tagged as C :)
It's my mistake -- I wrongly tagged it as C++ without realizing dcraw was in fact written in C. This appears to be one of the few things that is genuinely different between C and C++.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.