2

So I'm doing a course on C. One of the assignments is to look at and understand the code for sorting 5 grades(numbers). I copied the professor's code to MVS but it came up with errors. One of the issues I solved, as you can see by the comments in the code. But I don't understand how the professor managed to compile.

So my question is: how can the second error be solved?

int w[how_many];//error: expression must have a constant value.

Anyone care to help?

I'm using Visual studio. Tried "disable language ext.", rename source file from .cpp to .c and changed to "compile as C code (/TC)"

#include <stdio.h>
#define SIZE 5

void print_array(int how_many, int data[], const char* str)
{
    int i;
    printf("%s", str);

    for (i = 0; i < how_many; i++)
        printf("%d\t", data[i]);
}

void merge(int a[], int b[], int c[], int how_many)
{
    int i = 0, j = 0, k = 0;

    while (i < how_many && j < how_many)
        if (a[i] < b[j])
            c[k++] = a[i++];
        else
            c[k++] = b[j++];
    while (i < how_many)
        c[k++] = a[i++];
    while (j < how_many)
        c[k++] = b[j++];

}


void mergesort(int key[], int how_many) 
{
    
    int j, k;
    int w[how_many];//error: expression must have a constant value


    for (k = 1; k < how_many; k *= 2)
    {
        for (j = 0; j < how_many - k; j += 2 * k)
            merge(key + j, key + j + k, w + j, k);
        for (j = 0; j < how_many; j++)
            key[j] = w[j];
    }
}

int main(void)
{
    //const int SIZE = 5; // removed because of error and added #define SIZE 5
    int a[SIZE] = { 67, 82, 83, 88, 99 };// error: needs constant value, solved by adding #define SIZE 5
    
    print_array(SIZE, a, "My grades\n");
    printf("\n\n");
    mergesort(a, SIZE);
    print_array(SIZE, a, "Sorted grades\n");
    printf("\n\n");
    return 0;

}
DokuDoki
  • 77
  • 1
  • 4
SMV
  • 21
  • 2
  • 3
    Visual Studio has only limited support for C (C89 to be precise). Variable-Length Arrays are a C99 feature, which the Visual Studio compiler does not support – UnholySheep Sep 29 '20 at 19:23
  • @UnholySheep VLA cannot be initialized. – Antti Haapala -- Слава Україні Sep 29 '20 at 19:29
  • @AnttiHaapala the line OP points out as giving an error does not attempt to initialize the array, so I'm unsure what you are referring to – UnholySheep Sep 29 '20 at 19:32
  • @OP are you saying that you were able to compile this before you moved to visual studio? Or the professor said he was able to compile? To me it looks like he purposely put errors in the assignment for you to solve. – Spectrem Sep 30 '20 at 05:23
  • @Spectrem -The professor was able to compile. I think he did it from his Mac, using GCC/GNU. But I don't think he purposely put in errors on this assignement. This is a beginner course you see. – SMV Sep 30 '20 at 19:26

3 Answers3

2

The solution is further down, but first, the failure here:

int w[how_many];//error: expression must have a constant value

is because the MSVC compiler does not support Variable-length Arrays (VLA). C99 and newer family of ANSI C compilers support VLA.

So, the solution here is to get a different compiler.

Note:

VS 2019 (16.8) will include /std:c11 and /std:c17 standards switches. See this blog post. Because the MSVC compiler does not support Variable-length Arrays (VLA) it does not claim C99 conformance. Note that these switches enable the new C99 preprocessor covered in this blog post

(From here: Is there any option to switch between C99 and C11 C standards in Visual Studio?)

So my question is: how can the second error be solved?

Before C99, C programmers that did not know the length of an array until run-time used dynamic memory allocation. In your example, this:

int w[how_many];

could be implemented as:

int *w = calloc(how_many * sizeof(*w));
if(w)
{
    memset(w, 0, how_many);//zero the new memory space. (VLA needs this too)
    //use variable in code
    ...
    free(w); //always free when done, (VLA does not require)
}

Edit to address OP later content added to post,

const int SIZE = 5;
int a[SIZE] = { 67, 82, 83, 88, 99 };

This is not a valid C VLA as it is not (and never has been ) legal to initialize a VLA in C. (It is however legal in C++)

This however is legal: (as 5 is a constant value.)

#define SIZE 5
int a[SIZE] = { 67, 82, 83, 88, 99 };
ryyker
  • 22,849
  • 3
  • 43
  • 87
1

That code is not proper standard C.

int main(void) {
    const int SIZE = 5;
    int a[SIZE] = { 67, 82, 83, 88, 99 };
}

is not valid C89, because it has a variable-length array. It is not valid C99, C11, or C18, because a variable-length array cannot be initialized.

It is valid C++ though, because an array whose dimensions are specified with a const int is of static type.

Additionally Clang C compiler compiles it, but Gnu C Compiler rightfully refuses to compile:

% gcc vla.c
vla.c: In function ‘main’:
vla.c:49:5: error: variable-sized object may not be initialized
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |     ^~~
vla.c:49:21: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                     ^~
vla.c:49:21: note: (near initialization for ‘a’)
vla.c:49:25: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                         ^~
vla.c:49:25: note: (near initialization for ‘a’)
vla.c:49:29: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                             ^~
vla.c:49:29: note: (near initialization for ‘a’)
vla.c:49:33: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                                 ^~
vla.c:49:33: note: (near initialization for ‘a’)
vla.c:49:37: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                                     ^~
vla.c:49:37: note: (near initialization for ‘a’)

% clang vla.c
% clang vla.c -pedantic
vla.c:49:11: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]
    int a[SIZE] = { 67, 82, 83, 88, 99 };
          ^~~~
1 warning generated.

Suggested solution: get yourself a new professor.

1

Re:

So my question is: how can the second error be solved?

int w[how_many];//error: expression must have a constant value.

You can allocate memory for that array w like that:

int* w = malloc(how_many * sizeof(int));
Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27