initialize array size from another array value - c++

#include<iostream>
using namespace std;
const int vals[] = {0, 1, 2, 3, 4};
int newArray[ vals[2] ]; //"error: array bound is not an integer constant"
int main(){
return vals[2];
}
//returns 2 if erroneous line is removed
Why doesn't this work?

Unfortunately you can't do that in standard C++ because vals[2] is not a constant expression! In the coming standard you would have constexpr(implemented in g++ 4.6) to request compile-time evaluation easily:
#include<iostream>
using namespace std;
constexpr int vals[] = {0, 1, 2, 3, 4};
int newArray[ vals[2] ]; // vals[2] is a constant expression now!
int main(){
return vals[2];
}

It's possible that the value of a const expression is not even known at compile time. For example, you can initialize a constant with something returned from a function, like
const int size = rand(); // random size
So it is not that constant as you might think

The C++ compiler can only allocate an array with a size known at compile time. If you want to allocated a variable size piece of memory, use the new operator.

Related

How to make an unknow size array global? [duplicate]

I am having the following issue with my code:
int n = 10;
double tenorData[n] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Returns the following error:
error: variable-sized object 'tenorData' may not be initialized
Whereas using double tenorData[10] works.
Anyone know why?
In C++, variable length arrays are not legal. G++ allows this as an "extension" (because C allows it), so in G++ (without being -pedantic about following the C++ standard), you can do:
int n = 10;
double a[n]; // Legal in g++ (with extensions), illegal in proper C++
If you want a "variable length array" (better called a "dynamically sized array" in C++, since proper variable length arrays aren't allowed), you either have to dynamically allocate memory yourself:
int n = 10;
double* a = new double[n]; // Don't forget to delete [] a; when you're done!
Or, better yet, use a standard container:
int n = 10;
std::vector<double> a(n); // Don't forget to #include <vector>
If you still want a proper array, you can use a constant, not a variable, when creating it:
const int n = 10;
double a[n]; // now valid, since n isn't a variable (it's a compile time constant)
Similarly, if you want to get the size from a function in C++11, you can use a constexpr:
constexpr int n()
{
return 10;
}
double a[n()]; // n() is a compile time constant expression

Function to return size off array always returns 2

I was brushing up on my C++ (using eclipse and cygwin) by writing functions over arrays.
I have the following code:
int getArraySize(int a[]){
int size = sizeof(a)/sizeof(a[0]);
return size;
}
int main(void) {
int arr[5] = {0, 1, 2, 3, 4};
string s = "size of array: ";
cout << s << getArraySize(arr) << endl;
cout << s << sizeof(arr)/sizeof(arr[0]) << endl;
return EXIT_SUCCESS;
}
I expect to get this output:
size of array: 5
size of array: 5
but instead I get this:
size of array: 2
size of array: 5
I've tried this program with other sizes of arrays, and the function getArraySize()
always returns 2. Anyone know what's up?
This looks like an array declaration, but it is not:
int getArraySize(int a[]){
This is just a pointer-to-int. Therefore sizeof(a) / sizeof(a[0]) will just give you the ratio between the size of a pointer and the size of the pointed-to thing. The situation does not change if you put a number between the brackets, like this:
int getArraySize(int a[5]){
To the C++ compiler, that is the same as int getArraySize(int *a). C++ does not pass arrays by value. It passes a pointer to the first element of the array. When you give an array argument, the argument decays to a pointer.
The sizeof() operator will give you the total number of bytes in an array when you pass it an actual array variable, as in this:
int arr[5] = {0, 1, 2, 3, 4};
int arr_size = sizeof(arr) / sizeof(arr[0]);
Unfortunately the C++ syntax here is a bit misleading.
You cannot pass an array to a C++ function, you can only pass a pointer to the first element.
In C++ the declaration
void foo(int x[])
is EXACTLY the same as
void foo(int *x)
Even if you put a size between brackets as in
void foo(int x[10])
the number 10 is not a syntax error but will be completely ignored.
You however infer an array size from a template function, using a somewhat weird syntax:
template<typename T, size_t N>
size_t ArraySize(T (&)[N])
{
return N;
}
The sizeof(x)/sizeof(x[0]) trick works only if used in a macro... it cannot be placed in a function.
You are taking the size of int a[] which is really a pointer
it looks like you are on a 64 bit machine so:
sizeof(64 bit pointer) = 8
sizeof (int) = 4
8/4 = 2
On a 32 bit machine you would get a 1
The problem is that you are not getting the size of arr and there really isn't a way to do that until c++11 where you can use a std::array instead
I think your problem is that c++ passes arrays by reference hence you are simply dividing the size of addresses.

Array[n] vs Array[10] - Initializing array with variable vs numeric literal

I am having the following issue with my code:
int n = 10;
double tenorData[n] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Returns the following error:
error: variable-sized object 'tenorData' may not be initialized
Whereas using double tenorData[10] works.
Anyone know why?
In C++, variable length arrays are not legal. G++ allows this as an "extension" (because C allows it), so in G++ (without being -pedantic about following the C++ standard), you can do:
int n = 10;
double a[n]; // Legal in g++ (with extensions), illegal in proper C++
If you want a "variable length array" (better called a "dynamically sized array" in C++, since proper variable length arrays aren't allowed), you either have to dynamically allocate memory yourself:
int n = 10;
double* a = new double[n]; // Don't forget to delete [] a; when you're done!
Or, better yet, use a standard container:
int n = 10;
std::vector<double> a(n); // Don't forget to #include <vector>
If you still want a proper array, you can use a constant, not a variable, when creating it:
const int n = 10;
double a[n]; // now valid, since n isn't a variable (it's a compile time constant)
Similarly, if you want to get the size from a function in C++11, you can use a constexpr:
constexpr int n()
{
return 10;
}
double a[n()]; // n() is a compile time constant expression

reference to an array in c++

Question is make an array of 10 integers that's fine
int array[10];
Now question is
how to make a reference to an array which I have declared above ?
I tried this
int &ra = a;
But it's giving me error...
Please provide me details about this error and how to make reference of an array.
int (&ra)[10] = a;
Alternatively, you can use a typedef to separate this into the type for "array of 10 ints" and having a reference there-to, as in:
typedef int int10[10];
int10& my_ref = a;
The problem with your int &ra = a; is that it tells the compiler to create a reference of type int that refers to an array of 10 ints... they're just not the same thing. Consider that sizeof(int) is a tenth of the size of an array of ten ints - they occupy different amounts of memory. What you've asked for with the reference's type could be satisfied by a particular integer, as in int& ra = a[0];.
I appreciate it's a bit confusing that int* p = a; is allowed - for compatibility with the less type-safe C, pointers can be used to access single elements or arrays, despite not preserving any information about the array size. That's one reason to prefer references - they add a little safety and functionality over pointers.
For examples of increased functionality, you can take sizeof my_ref and get the number of bytes in the int array (10 * sizeof(int)), whereas sizeof p would give you the size of the pointer (sizeof(int*)) and sizeof *p == sizeof(int). And you can have code like this that "captures" the array dimension for use within a function:
template <int N>
void f(int (&x)[N])
{
std::cout << "I know this array has " << N << " elements\n";
}
The reference to array will have type int (&a)[10].
int array[10];
int (&a)[10] = array;
Sometimes it might be useful to simplify things a little bit using typedef
typedef int (&ArrayRef)[10];
...
ArrayRef a = array;
This is a reference to an array of of ints of size 10:
int (&ra)[10];
so
int (&ra)[10] = a;
You can typedef the array type (the type should not be incomplete) as follow:
#define LEN 10
typedef int (array)[LEN];
int main(void)
{
array arr = {1, 2, 3, 4, 5}; //define int arr[10] = {1, 2, 3, 4, 5};
array arr2; //declare int arr[10];
array *arrptr = &arr; // pointer to array: int (*arrptr)[10] = &arr;
array &&arrvef; // declare rvalue reference to array of 10 ints
array &ref = arr; // define reference to arr: int (&ref)[10] = arr;
}

Aggregates in c++

In the following code why is that the two statements are illegal
const int i[] = { 1, 2, 3, 4 };
// float f[i[3]]; // Illegal
struct S { int i, j; };
const S s[] = { { 1, 2 }, { 3, 4 } };
//double d[s[1].j]; // Illegal
int main() {}
Why are they illegal? The textual definition is as follows which i didn't understand.
"In an array definition, the compiler must be able to generate code
that moves the stack pointer to accommodate the array. In both of the
illegal definitions above, the compiler complains because it cannot
find a constant expression in the array definition."
Thanks in advance.
Array sized need to be constant expressions. Try this:
constexpr int i[] = { 1, 2, 3, 4 };
float f[i[3]];
The constexpr keyword was introduced in C++11. Previous versions of C++ had no concept of such general constant expressions, and there was no equivalent concept.
Because C++ doesn't support variable-length arrays, and s[1].j is not a compile-time constant.
What that quote refers to is the fact that f and d are in automatic storage. The run-time will clean their memory automatically when they go out of scope. As such, it must know the size beforehand.
because d is static array, that means that it's size has to be know at compilation time.
Therefore you can't use non-const variables as size parameter.
But you can try
const int i = 3;
double d[i];
for example.