tags:

views:

119

answers:

5

I need to be able to set the size of an array based on the number of bytes in a file.

For example, I want to do this:

// Obtain the file size.
    fseek (fp, 0, SEEK_END);
    size_t file_size = ftell(fp);
    rewind(fp);

// Create the buffer to hold the file contents.
    char buff[file_size];

However, I get a compile time error saying that the size of the buffer has to be a constant.

How can I accomplish this?

+2  A: 

You should use a std::vector and not an array.

Real arrays require you to specify their size so that the compiler can create some space for them -- this is why the compiler complains when you don't supply a constant integer. Dynamic arrays are represented by a pointer to the base of the array -- and you have to retrieve the memory for the dynamic array yourself. You may then use the pointer with subscript notation. e.g.,

int * x;
x = (int *) malloc( sizeof(int) * 
                    getAmountOfArrayElements() /* non-const result*/ 
                  );
x[5] = 10;

This leads to two types of problems:

  1. Buffer over/under flows : you might subscript-index past either end of the array.

  2. You might forget to release the memory.

Vector provides a nice little interface to hide these problems from you -- if used correctly.

Hassan Syed
This is tagged `C++`. You should use `new`, not `malloc()`. But once you make all this exception-safe, you'd better off using `std::vector` anyway...
sbi
You down-vote for such a trivial reason....
Hassan Syed
@Hassan: I wouldn't down-vote for a trivial reason, but I don't consider using `malloc()` in C++ programs trivial. That was advised against in the very first edition of _Effective C++_ by Scott Meyers in 1991 - I don't think the latest edition even mentions it, because it's such a well-known rule nowadays.
sbi
Also, there is http://stackoverflow.com/questions/2372780/2372820#2372820
sbi
And what would you do when you want to allocate objects on thread local memory ? Try to shoehorn the feature into `new` ?
Hassan Syed
@Hassan: You would not use malloc either.
RaphaelSP
No but it wouldn't be `new` either. So what are we supposed to do then ? Not use a native API in favour of new ?
Hassan Syed
I think the point sbi is making is against `malloc`. In such a case, you wou probably use std::vector with a custom allocator...
RaphaelSP
What if this is for a multicore embedded device, and the company doesn't allow you to use the STL ? Would you still just stick to new ? Allocation is a concept, and you use what your coding conventions ask of you .... but to mark a perfectly valid response down because I chose to illustrate my reply using a c idom is just off.
Hassan Syed
Well, in such a situation, you know pretty much what you're doing and you don't have a choice anyway, so the usual "don't do this" rules don't apply :-)But advocating for `malloc` for the general case is still a bit against the unwritten rules.
RaphaelSP
+1  A: 

Replace

char buff[file_size];

with

char *buff = new char[file_size];

and once the use of the buff is done..you can free the memory using:

delete[] buff;
codaddict
No, don't. There's no good reason to use `new []` here instead of `std::vector`.
Jerry Coffin
I'm down-voting because there is no mentioned of `vector`, sorry. Answer's shouldn't suggest raw memory handling when a standard type will do. It encourages bad programming.
GMan
+10  A: 

Use a vector.

std::vector<char> buff(file_size);

The entire vector is filled with '\0' first, automatically. But the performance "lost" might not be noticable. It's certainly safer and more comfortable. Then access it like a usual array. You may even pass the pointer to the data to legacy C functions

legacy(&buff[0]); // valid!
Johannes Schaub - litb
Yes, `std::vector` is the way to go. But I don't see why his code is failing in the first place. He is basically declaring a variable-length array, and I can't see anything illegal in that? It works when I try it in GCC.
Hans W
It is legal C99, but not C++98.
RaphaelSP
@Hans: Variable-length array are a C99 feature. C++, however, is based on C89. So they aren't a C++ feature.
sbi
RaphaelISP and sbi: Thanks for clearing that up. I was uncertain as to whether variable length arrays had been included in C++. I also now note that GCC complains about this if invoked with `-pedantic`.
Hans W
A: 

Problem is that buff needs be created on the heap (instead of stack). Compiler want s to know the exact size to create on the stack.

char* buff = new char[file_size];
PoweRoy
There's no reason to use `new[]` here instead of `std::vector`.
Jerry Coffin
The question is setting the size of the array, not vector. I agree that vector is better but that's another issue. Whats the reason of the downvotes?
PoweRoy
I downvoted because using new[] in this (or almost any) situation is simply not a good suggestion. Yes, the question uses the word "array" -- if he'd known enough to ask about "vector" instead, he wouldn't have needed to ask. It's clear that he wants is some data storage -- and equally clear that `new[]` isn't a good way to get that.
Jerry Coffin
+1  A: 

There are two points in your question I'd like to cover.

  1. The actual question, how do you create the array. Johannes answered this. You use a std::vector and create it with a size allocation.
  2. Your error message. When you declare an array of some type, you must declare it with a constant size. So for example

    const int FileSize = 1000;

    // stuff

    char buffer[FileSize];

is perfectly legitimate.

On the other hand, what you did, attempting to declare an array with variable size, and then not allocating with new, generates an error.

Liz Albin