0

I am reading this to consider about how to dynamically allocate memory for a two-dimensional array.

I notice that a variable value cols can be used as size to define int (*arr)[cols], as C language has variable-length arrays(VLA) feature, then I try modifying the code into C++ like:

#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>

void* allocate(size_t rows, size_t cols)
{
    int (*arr)[cols] = (int (*)[cols])malloc(rows *sizeof(*arr));
    memset(arr, 0, rows *sizeof(*arr));
    return arr;
}

int main() {
    size_t rows, cols;
    scanf("%zu %zu", &rows, &cols);

    int (*arr)[cols] = (int (*)[cols])allocate(rows, cols);
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%3d", arr[i][j]);
        }
        printf("\n");
    }
}

compile with gcc 11.2 -std=c++11

To my surprise, this works well and compiler does not report any warning. AFAIK C++ has no VLA feature, I used to think this code should be forbidden. So why could this work?

rustyhu
  • 1,912
  • 19
  • 28
  • 6
    It is indeed not standard C++, some compilers allow it as an extension. – Pepijn Kramer Oct 05 '21 at 06:31
  • It's a diagnosable error in standard C++. g++ supports VLAs as a non-standard extension by default. Turn up the warning/error levels to get a diagnostic about VLAs. – Peter Oct 05 '21 at 06:31
  • 1
    If you program in C++, may I ask why you use `scanf` and `printf` instead of the standard C++ streams `std::cin` and `std::cout`? If the shown code is copied from somewhere else, are you sure it's from a C++ program and not a C program originally? The only C++ specific parts of the code are those header files, nothing else. I think that whatever resource you got the code from, don't use it as a reference or learning resource for C++. – Some programmer dude Oct 05 '21 at 06:35
  • 2
    Add `-pedantic-errors` flag to get an error. – HolyBlackCat Oct 05 '21 at 06:36
  • @Peter I did compile with option `-std=c++11`, should the g++ extension be disabled? – rustyhu Oct 05 '21 at 06:36
  • @Someprogrammerdude The original code is in `C`, I only modify some specific parts such as headers and type cast in front of `malloc`, in fact I concern about the difference between `C` and `C++`, originally I want to verify that VLA is not supported by `C++` so this pattern to allocate dynamic 2-dim array maybe quite limited. Thanks for your advice. – rustyhu Oct 05 '21 at 06:45
  • 1
    `-std=c++11` simply specifies a dialect. You *also* need to enable options that make `g++` more picky with warnings and to treat warnings as errors. `-pedantic-errors` is the minimum, but I also turn on `-Wall -Weffc++ -Wextra` and a few others, as well as enabling `-Werror` (which treats warnings as errors). Essentially, if a compiler *can* complain about something, I want it, and I aim to build without warnings or errors (on multiple compilers where practical). – Peter Oct 05 '21 at 06:46
  • Set the compiler flags for C++ Standard conformance - live - https://godbolt.org/z/bbEoT7W3e – Richard Critten Oct 05 '21 at 06:54

1 Answers1

3

-std=c++11 doesn't mean "compile strictly according to C++11" but "enable C++11 features." Just as -std=gnu++11 (the default setting) means enable gnu++11 features, which is a superset of C++11.

To get strictly compliant behavior, you must use -std=c++11 -pedantic-errors. And then you get this:

error: ISO C++ forbids variable length array 'arr' [-Wvla]

See What compiler options are recommended for beginners learning C? for details. It was written for C but applies identically to g++ as well.

Lundin
  • 195,001
  • 40
  • 254
  • 396