9

Why is this C code illegal in Visual Studio 2013 Ultimate?

const unsigned int x = 64;
char resultBufNative[x+1];

It gives error C2057: expected constant expression.


Original question

I'm completely baffled by this one.

Relevant function:

jstring Java_com_nabto_api_NabtoCApiWrapper_nabtoGetSessionToken(JNIEnv* env, jclass thiz, jobject sessionObj)
{
    const size_t size = 64;
    char resultBufNative[size+1];

    size_t resultLen;

    //Get the session
    nabto_handle_t session;
    session = (nabto_handle_t) (*env)->GetDirectBufferAddress(env, sessionObj);

    nabto_status_t nabtoStatus = nabtoGetSessionToken(session, resultBufNative, size, &resultLen);

    if (nabtoStatus == NABTO_OK && resultLen <= size) {
        // Terminate char array, convert to java string, free buffer and return result
        resultBufNative[resultLen] = 0;
        jstring result = (*env)->NewStringUTF(env, resultBufNative);
        //nabtoFree(resultBufNative);
        return result;
    }
    else {
        return NULL;
    }
}

Error message: error C2057: expected constant expression

On line char resultBufNative[size+1];

To me, that makes the relevant code as such:

    const size_t size = 64;
    char resultBufNative[size+1];

And apparently, const size_t + 1 is not a constant expression.

There are no defines or macros size dicking about (replacing it with xyzabc gives the same error). size_t is defined as typedef unsigned int __w64 size_t when I mouseover size_t in my IDE (Visual Studio Ultimate 2013).

After the C2057 expected constant expression error, the compiler gives 2 more errors:

C24166: cannot allocate array of size 0
C2133: 'resultBufNative': unknown size

For the same line of code. Naturally, these are because it doesn't know what size + 1 is, so it becomes 0.

Using

    constexpr const size_t size = 64;
    char resultBufNative[size+1];

Gives error C2065: 'constexpr' : undeclared identifier.

Using

    const size_t size = 65;
    char resultBufNative[size];

Gives error C2057: expected constant expression.

Using

    static const size_t size = 64;
    char resultBufNative[size+1];

Gives error C2057: expected constant expression.

Using

    const unsigned int x = 64;
    char resultBufNative[x+1];

Gives error C2057: expected constant expression.

I guess what I want to do is not supported.

Pimgd
  • 5,983
  • 1
  • 30
  • 45

2 Answers2

6

In C89 mode, the array size must be a compile time constant but size is not one. const keyword means read only, not compile time constant (this is different in C++). So you have few options here:

1) Compile in C99 mode which supports VLAs.

2) Use fixed size arrays:

   char resultBufNative[64+1];

3) Use

#define size 64

which is basically same as option (2) except preprocessor does that replacement for you.

4) Use enum as suggested by bluepixy, which is a compile time constant unlike const.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • Hmm... how do I compile in C99? – Pimgd Nov 12 '14 at 10:34
  • If you are using GCC or clang, it would be: `gcc -std=c99 -Wall file.c` / `clang -std=c99 -Wall file.c`. – P.P Nov 12 '14 at 10:35
  • 1
    I wish I was using gcc =). Looking around the internet and the comments here, it seems I'll have to use the hacky workarounds since VS doesn't have C99. I wish Visual Studio supported C99. – Pimgd Nov 12 '14 at 10:36
  • 5) `char *resultBufNative = malloc(size + 1);` – BLUEPIXY Nov 12 '14 at 10:38
  • 1
    @BLUEPIXY then I'll have to check for NULL, and I'd rather not. – Pimgd Nov 12 '14 at 10:39
  • @Pimgd I'd prefer `enum` in C89 as it's both compile time constant and type safe. It's not hacky at all. – P.P Nov 12 '14 at 10:41
  • @BlueMoon from a syntactical perspective, I get your point, but I prefer to use enums for enumerations, and not things like constant array sizes. I'll use that, though. – Pimgd Nov 12 '14 at 10:42
  • VS2015 is supposed to support C99, but I'm not sure how to turn it on – tofutim Dec 01 '15 at 17:57
  • You can turn it on by compiling as Cpp /Tp – tofutim Dec 01 '15 at 18:10
  • @tofutim Yes, it now fully supports C99: https://msdn.microsoft.com/en-us/library/hh409293.aspx But I have no idea how to turn it on. – P.P Dec 01 '15 at 18:11
  • @l3x Project / Properties / Configuration Properties / C/C++ / Advanced / Compile As / "Compile as C++ Code (/TP)" – Bachor Apr 15 '16 at 07:05
-1

An updated solution is to compile as C++ using /Tp in Visual Studio 2015. While not perfect, the C++ compiler supports a large subset of C99.

tofutim
  • 22,664
  • 20
  • 87
  • 148