Array size allocation at compile time, expecting constant value [duplicate] - c++

This question already has answers here:
Enabling VLAs (variable length arrays) in MS Visual C++?
(5 answers)
Closed 8 years ago.
// testing1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <iostream>
#include<conio.h>
using namespace std;
struct Data_point {
double x;
double y;
};
void PlotThis(unsigned int n )
{
Data_point graph[n]; //shows error here
//do something else, dont worry about that
}
int main ()
{
unsigned int nSamples;
cout << "Please enter nSamples: ";
cin >> nSamples;
PlotThis(nSamples);
return 0;
}
This shows error when compiling:
Error 1 error C2057: expected constant expression testing1.cpp 23
Error 2 error C2466: cannot allocate an array of constant size 0 testing1.cpp 23
Error 3 error C2133: 'graph' : unknown size testing1.cpp 23
Line 23 is Data_point graph[n]; //shows error here
It is showing unknown size even though I am passing it the value from main(). It is asking for the value (the size of graph i.e n) at the compile time. Does that mean array size allocation takes place at compile time? How to solve this

C++ doesn't support arrays with size determined at run-time. You could switch to using the Vector class instead.
std::vector<Data_point > graph;
To follow the logic you're using: In PlotThis you could use std::vector::resize to resize the container to contain n elements.
void PlotThis(unsigned int n){
graph.resize(n); // Resize Vector container
...
Also with std::vector:
"compared to arrays, vectors consume more memory in exchange for
the ability to manage storage and grow dynamically in an efficient way."
This means you have the option to not worry about specifying the size of the vector and just adding elements as you need to. So you could have a loop determine how many elements are added (n) in your method - possible to use std::vector::push_back. If you do this then just make sure to clear the vector at some point so you don't re-use old data - possible to use std::vector::clear.

You can use some containers, for example vector, deque etc...
void PlotThis(unsigned int n)
{
std::vector<Data_point> graph(n);
//do something else, dont worry about that
}
Or allocate memory for array dynamically:
//C++
void PlotThis(unsigned int n)
{
Data_point* graph = new Data_point[n];
//do something else, dont worry about that
//Remember to free memory
delete graph;
}
//C
void plot_this(unsigned int n)
{
Data_point* graph = (Data_point*) malloc(sizeof(Data_point) * n);
//do something else, dont worry about that
//Remember to free memory
free(graph);
}

Related

Parameter cannot be used as a constant [duplicate]

This question already has answers here:
Declaring Variable length arrays [duplicate]
(3 answers)
Closed 1 year ago.
I have just finished my code, I am stuck on these last two errors:
"the value of parameter "n" cannot be used as a constant." I am using "int n" in my function to calculate average time.
void findavgTime(int option, int pids[], int arrivals[], int n, int bursts[], int quanta) {
int resp[n], ta_time[n], avg_resp_time = 0, avg_ta_time = 0;
How should I go by this?
In C++, the size of an array must be a compile time constant. So you cannot write code like:
int n = 10;
int arr[n]; //incorrect
Correct way to write this would be:
const int n = 10;
int arr[n]; //correct
For the same reason the following code is incorrect in your code as well:
int resp[n], ta_time[n];//incorrect because n must be a compile time constant
You can use std::vector<> for your purpose instead of using built in arrays. So instead of creating arrays you can have/create std::vector named resp and ta_time as follows:
//n denotes the size. You can also use std::vector::reserve for requesting that the vector capacity be at least enough to contain n elements
std::vector<int> resp(n);
std::vector<int> ta_time(n);
Consider replacing your variable-length arrays:
int resp[n], ta_time[n]
with modern C++ std::vector instances:
#include <vector> // for std::vector
std::vector<int> resp(n);
std::vector<int> ta_time(n);
You can still access vector elements using the usual v[i] syntax with a 0-based index, e.g.:
resp[2] = 100; // Access the 3rd element in the vector
VLAs (variable-length arrays) are not part of the C++ standard.
You can only create arrays with compile-time known size, e.g.
constexpr int n = 100; // compile-time constant
int resp[n];

How can I define large multidimensional arrays in c++ without getting this error?

My programming knowledge is very basic but usually enough to get by for what I need it for.
I'm using visual studio and trying to define large arrays of 4 dimensions (maybe more) of size up to [20][20][20][10000].
At first I was defining an array as int array[5][5][5][900] which was working fine. I then tried defining a new array, exaclty the same size but with a different name and got an unhandled exception error on chkstk.asm Find next lower page and probe
cs20:
sub eax, PAGESIZE ; decrease by PAGESIZE
test dword ptr [eax],eax ; probe page.
jmp short cs10
I tried defining as double and long double, and using a vector but seems to make no difference. I'd like to increase the size also and possible add further dimensions.
Can someone please explain a simple way to make an array like this without this happening?
The array elements only need to contain 0 or 1
The issue is that the array you've specified will be very large in size (20 * 20 * 20 * 900 = 7.2 million). Since that data is stored on the stack you're probably seeing a stack overflow.
You'll probably want to allocate something that large with new like:
auto test = new int[20][20][20][900];
test[0][1][0] = 0;
// when you're done with it, you'll need to delete though
delete[] test;
which will put it in the (much larger) heap
You can consider this approach:
#include <vector>
int main()
{
std::vector<std::vector<std::vector<std::vector<bool>>>> tab4;
int n1 = 10; // 1st dimension
int n2 = 20; // 2nd dimension
int n3 = 30; // 3rd dimension
int n4 = 10000; // 4th dimension
tab4.resize(n1);
for (auto& v : tab4)
{
v.resize(n2);
for (auto& w : v)
{
w.resize(n3);
for (auto& u : w)
{
u.resize(n4);
}
}
}
tab4[1][12][23][4000] = 9999;
}
Pros:
This code is exception-safe and leak-free
The vector can be easily resized, should the need appear.
The size of each of the vector dimensions need not be compile constants
Beginners should not be exposed to bare pointers where more robust, safe and easy to use alternatives exist.
Cons:
More code is needed (this is not a serious drawback)
The allocated memory is not contiguous (this may be of some importance to advanced users only, can be circumvented, but I'm not aware of a solution that could be advised to beginners)
Alternative solution
This can be used if the sizes of the vector are fixed at compile-time. One vector is used to allocate the memory on the heap automatically, without resorting to bare pointers, operator new, etc.
#include <array>
#include <vector>
int main()
{
// vector [10][20][30][1000]
std::vector<std::array<std::array<std::array<bool, 10000>, 30>, 20>> tab4 (10);
tab4[1][12][23][4000] = 9999;
}
I personally like std::, but sometimes there's too many of them. This can be achieved like this:
using std::array;
std::vector<array<array<array<bool, 10000>, 30>, 20>> tab4 (10);

Why are vectors' size static and we still can add more values?

I'm a complete beginner to C++ but I have some basics knowledge in programming (Python mainly) and I'm trying to learn C++. As the question implies, vectors have static sizes (at least what I've read in my learning material) but we still can add more values to what the size authorize. I wrote a simple code to know what error I get if I pass more values to a vector than the limit authorized by it's size and surprisingly I didn't get any error.
The code are these simple lines:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int it=0,a;
vector<int> v(10);
for(a=1; a<21; a++)
{
v[it]=x;
cout << v[it] << endl;
it++;
}
cout<<"Values stored in v";
for(i=0;i<it;i++)
cout<<v[i]<<" ";
cout<<endl;
cout<<"Vector's size : "<<v.size()<<endl;
return 0;
}
What I get with cout<<"Values stored in v"; are all values from 1 to 20, but I still get that the size is 10.
If that can helps I'm on Windows 10 x64 and using Qt Creator compiler.
What is fixed is
sizeof( vector<int> )
A vector can contain varying number of elements, but that elements are stored on the heap, hence do not contribute to the vectors sizeof. The number of elements is v.size() (and that can change).
You create a vector with 10 elements:
vector<int> v(10);
But then you attempt to access elements that do not exist in the loop. For example v[10] will not cause a compiler error, it is also not guaranteed to cause a runtime error. Nevertheless, it is guaranteed wrong. Accessing the vector out of bounds causes undefined behavior. The output of the code could be anything.

Create C++ variable length global arrays

I would like to create a variable length global array so that I can use them in any functions such as main() or anything.
#include <iostream>
int g_t_step[];
int main()
{
g_t_step[1]=1;
std::cout << g_t_step[1];
}
In general, global variables are not the way to go except for logging. It's easy to loose track of which function/method will modify the content of your array and it can become hard to debug as your code base grows. If you give more details about what your are trying to achieve, it will be easier to help you.
By seeing your code sample I'm guessing you're quite new to C++, the code you wrote doesn't compile. The variable g_t_step as you've defined it here should be initialized as well, for example:
int g_t_step[] = {1, 2, 3};
However, if you want your array to be resizable, you cannot declare it this way because g_t_step will be of size 3 no matter what you try to do (in my example because there are 3 numbers on the left side). The reason for that is because g_t_step is allocated on the stack which is defined at compile time.
If you want it to be resizable, it should be allocated on the heap like so:
#include <iostream>
int* g_t_step = nullptr;
int size = 0;
int capacity = 0;
int main() {
g_t_step = new int[10]; // heap allocation
capacity = 10;
g_t_step[0] = 4 // initialize the second element of the array
size = 1;
std::cout << g_t_step[0] << '\n';
return 0;
}
This would be the way to answer your question but it is very minimal, you have to keep track of the current size of your array and the number of elements in it yourself. The easy way is to use STL's std::vector template like so:
#include <iostream>
#include <vector>
// the static part is not necessary if you only have one file
// but is usefull if you define g_t_step in another source file
// which is then linked against the main
static std::vector<int> g_t_step;
int main() {
g_t_step.push_back(1); // initialize the first value...
g_t_step.push_back(2); // second...
g_t_step.push_back(3); // and third...
std::cout
<< g_t_step.size() << ' ' // output 3 because the vector contains 3 numbers
<< g_t_step.capacity() << ' ' // output 4
<< g_t_step[0] << ' ' // output 1
<< g_t_step[1] << ' ' // output 2
<< g_t_step[2] << '\n'; // output 3
}
The class std::vector keeps track of the number of elements (size()) and the size of the array (capacity()) which is always a power of 2 greater than the number of elements (4 in this case).
You could then write something like this:
static std::vector<int> vect;
void add_element(int e) {
vect.push_back(e);
}
int main() {
add_element(4);
add_element(5);
std::cout << vect[0] << ' ' << vect[1] << '\n'; // output: 4 5
}
But again, this is considered bad practice so without more details I wouldn't recommend using that unless it's for a small script.
For more information see:
std::vector
You can also look at static variables.
The concept of variable-length array is applicable on C99 but not in C++ standard. In an enhance way, you can take the help of vectors in C++. They have the ability to resize and reallocate the required memory to use them properly.
Assume the following example code and notice the comments:
#include <iostream>
#include <vector>
int main(void) {
// Example 1: Manually resizing the vector
// ---------------------------------------
std::vector<int> myVec;
int n = 100;
myVec.resize(n); // Similar work to that of VLAs
// Example 2: Dynamically managing the size of vector
// --------------------------------------------------
std::vector<int> myVec {10, 20, 30};
std::vector<int> myVec2;
myVec.push_back(10);
myVec.push_back(20);
// After this, the size of the vector will be increased by 2
// since two elements are inserted.
// You can erase() the vector elements and the sizes will be
// automatically reduced.
.
.
return 0;
}
On the other hand, you should not consider declaring the variables globally.
You are not initizing the array size.
This will give you error at compile time
As when you write
int a
then a variable "a" gets stored in stack memory with random address with size of int (depend on processor)
but when you write
int a[]
then stack memory needs the size of the array to allocate inside the stack
for eg int a[3];
this will aqcuire the size of 3*(size of int) inside the stack memeory
As I dicussed above is static allocation of array which is directly stored inside stack
but you can also allocate the array inside heap which is called a dynamic allocation. I think you have to first try the dynamic allocation by yourself

How to count the number of elements in an predefined array

I want to count the actual number of elements in the array.
but if I use sizeof() statement it gives me the size of array. not the number of elements present.
int main()
{
int a[10],n;
a[0]=1;
a[1]=5;
a[2]=6;
n=sizeof(a)/sizeof(a[0]);
cout<<"The size of array " <<n;
}
Here it gives me the n value as 10 not 3. Please suggest me a way to derive the number of elements without affecting the performance.
int a[10]; // This would allocate 10 int spaces in the memory;
a[0] = 1; // You are changing whats inside the first allocated space, but you are not changing the number of items in your C array.
Solution 1 (Easy) :
#include <vector>
vector<int> a;
a.push_back(1);
a.push_back(2);
size_t size = a.size(); // to get the size of your vector. would return 2. size_t is the actual type returned by size() method and is an unsigned int.
Solution 2 (Complicated) :
You could create an int variable that you could call e.g. numberOfElements and update it each time you add an element.
This solution is actually used in the implementation of the vector class.
As it have been already mentioned, you should use std::vector or std:array to achieve this behaviour. Declaring simple array means you allocate enough memory on the heap. There is not a way to determine whether this memory is "occupied" with something valid or not, since there is always something (after allocation there are random values on each index of the array).