-10

I'd like to make array from variable size as following.

int buff_size = width*height*3;
unsigned char buffer[buff_size];

but I've got an error message like this:

mfc_test5Dlg.cpp(418): error C2057: expected constant expression

How can I make variable size array?

cabot
  • 73
  • 1
  • 7
  • Besides your typo, which considering the error seems like not the main issue, VLA is a C99 feature not a C++ feature [some compiler support it as an extension](http://stackoverflow.com/a/21273849/1708801) but not Visual Studio. – Shafik Yaghmour Dec 03 '15 at 15:28
  • 1
    Your question is tagged with both c and c++. In c++ you cannot do that at all. you can do it in c if you fix syntax errors – Manos Nikolaidis Dec 03 '15 at 15:29
  • If you want to have a variable or array with dinamic size you may use 'pointers' and 'memory allocation'. Do some search and you should find examples. – Sina R. Dec 03 '15 at 15:47

4 Answers4

3

You have a ; lying around. Change

int buff_size; = width*height*3;

to

int buff_size = width*height*3;

Besides that; if you really want to have an array with variable length; you'll have to allocate it dynamically; You can do this in several ways:

C++ : new and delete:

unsigned char* buffer = new unsigned char[buff_size];
...
delete[] buffer;

C : malloc and free:

unsigned char* buffer = (unsigned char*) malloc(buff_size); // or malloc(sizeof(char) * buff_size)
...
free(buffer);
Chris Maes
  • 35,025
  • 12
  • 111
  • 136
  • 1
    This may fix the error but still leaves the OP using a variable length array which is non standard. They should use a `vector` or `new up an array. – NathanOliver Dec 03 '15 at 15:29
  • 2
    Considering the error `expected constant expression` I don't believe this is the actual problem. – Shafik Yaghmour Dec 03 '15 at 15:30
  • You're right; I added that to my answer – Chris Maes Dec 03 '15 at 15:34
  • `sizeof(char)` will **never** yield anything else than `1`. It is useless. – too honest for this site Dec 03 '15 at 15:42
  • you're right, but I like to keep the habit of putting the sizeof there in order to avoid errors with other types... I'll add your remark to the answer. – Chris Maes Dec 03 '15 at 15:49
  • Thanks. but I've got an error like this. mfc_test5Dlg.cpp(417): error C2440: 'initializing' : cannot convert from 'char *' to 'unsigned char *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast Build FAILED. Time Elapsed 00:00:31.40 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== – cabot Dec 04 '15 at 14:05
  • a minor typo: it should be "new unsigned char[buff_size]. I corrected my answer – Chris Maes Dec 04 '15 at 16:10
3

You can't have variable sized arrays in C++. If you absolutely want to you can dynamically allocate it but using a std::vector is almost always better, anyways, this is the dynamic way:

int buff_size = width*height*3;
unsigned char* buffer = new char[buff_size];
...

delete[] buffer;
Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
1

You'll want to avoid new and delete with raw pointers.

std::size_t const buff_size = width*height*3u;

1) Use std::vector<char> if possible:

std::vector<char> buffer{buff_size};

2) Use std::make_unique if available:

auto buffer = std::make_unique<char[]>(buff_size);

3) Use std::unique_ptr manually otherwise:

std::unique_ptr<char[]> buffer{new char[buff_size]};
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
0

In modern/safe/idiomatic C++ you make variable-size arrays with vector:

std::vector<unsigned char> buffer(buff_size);

All other options are unsafe (you either leak memory or access out-of-bounds more easily than necessary).

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • Can you explain why using `std::vector::operator[]` is less likely to access the data out of bounds compared to `std::unique_ptr::operator[]`? Actually, the other options are less-automated and thus more likely to be used in a wrong manner but that doesn't mean they are unsafe. – Pixelchemist Dec 03 '15 at 16:18
  • Those operators are equivalent (ignoring the fact that some implementations have bounds-checking in `vector::operator[]` in debug mode). However, consider `vector::at` which performs bounds-checking and should be preferred over `operator[]`. A `unique_ptr` offers no such functionality. – Emil Laine Dec 03 '15 at 16:20
  • Selecting `at` over `operator[]` usually requires some kind of problem-sensitivity in the first place (so you don't get safety for free... it's just cheapter ;)). Hands down `vector` is easier to use and I generally agree that it should always be preferred and used if possible. – Pixelchemist Dec 03 '15 at 16:27