I am new to c++ and I would appreciate if someone could help solving following problem.
When I want to create an array (Arr) with variable size (S), I do in the following way:
const int S=10;
int Arr[S];
However, in the code I am trying to write, I need to choose S from a Table. Let say I have following table:
int Table[3]={11, 21, 31};
and I choose S from the table and define Arr
const int S=Table[0];
int Arr[S];
I cannot compile this code because I get an error that S must have a constant have constant value.
I would appreciate any help/hint.
To fix the problem, you need to declare Table constexpr:
void foo() {
const int S=10;
int Arr[S];
constexpr int Table[3]={11, 21, 31};
constexpr int S2=Table[0];
int Arr2[S2];
}
Explanation: by declaring Table constexpr, you let compiler know that it knows it contents at compile time. Now it can be used whenver literal constants can be used, including array sizes. I'have shown the use of intermediate constexpr variable to illustrate this effect better, but you could use Table[0] as Arr2 size directly.
NB. constexpr is a keyword introduced in C++11, but I assume, it is safe to assume this dialect by default in 2016.
Related
I defined a const int array like this :
const int arr[] = { 100 , 200, 300, 400 };
Now i want to set one of the elements of above array as the length of another array like the following :
char buffer[arr[3]];
But it gave me a compile time error :
non-constant arguments or reference to a non-constant symbol
I studied this This question to solve my problem but i became confuse about these questions :
Why can't i set an element of a const array as the length of another array?
Are the elements of a const array constant or read only?
What is the differences between a const and read only statements in c?
Regards!
There are really two different kinds of constant "things" in C++.
The one that you know as the const keyword: you can't modify it at runtime.
And the one that's known as a constant value to the compiler at compile time.
That one would be:
constexpr int arr[] = { 100 , 200, 300, 400 };
C++ requires an array size to be a constexpr expression, and not just a const one. Some compilers let you get away with just a const size (and not even that, actually), but that's not the current C++ standard.
You might be wondering why, in this case, this is not a constant value at compile time. After all: it's right there. It's three digits. An integer. It can't go anywhere.
Well, that would be a different, pedantic question, but is mostly irrelevant. Your compiler is well within its rights to reject a non-constexpr expression in this case, as ill-formed. So it does. And you have no choice but to obey your compiler's demands.
I realized const and constexpr in the following statements :
const : To be evaluated at runtime and it's accepted by compiler and can't change in runtime.
const int a = std::cin.get(); // correct
const int b = 5; // correct
constexpr : To be evaluate at compile time
constexpr int b = std::cin.get(); // incorrect (because it evaluate in compile time, so compiler cannot forecast the value at compile time)
constexpr int b = 65; // correct
Now in my code as i understood, i think the char buffer is evaluate the array size at compile time and const int arr will be avaluate at runtime. so cannot set char buffer array length with a number that will be evaluate at runtime and we need a constant value.
Notice :
const int arr[] = { 100 , 200, 300, 400 }; // Evaluate at runtime
char buffer[arr[3]]; // Evaluate at compile time and cause error
So we need a const number that evaluated at compile time to set array length of the char buffer :
constexpr int arr[] = { 100 , 200, 300, 400 }; // Evaluate at compile time
char buffer[arr[3]]; // Evaluate at compile time
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 6 years ago.
I have looked at all the other posts with a similar topic, and none help, so please don't flag as a duplicate.
I am defining in main() a const int SIZE = 20;. Then, I pass this as an argument to my function, Mode:
int* Mode(int* numbers, int & mode, const int SIZE)
{
int occurences[SIZE];
// Calcualte mode
}
However, I get the error, expression must have a constant value.
My function call (in main) looks like this:
int* occurencesPtr = Mode(numbersPtr, mode, SIZE);
With SIZE being defined at the beginning to the literal 20.
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
I have even tried passing to the function a const int * const SIZEPtr = &SIZE, but that didn't work either. Help?
EDIT: I am not trying to use a variable size!! Notice that I have made SIZE a const everywhere! I just want to use that same SIZE constant to declare my array.
EDIT: Dynamic arrays are not what I need. I just want a normal, named, array, defined with a constant size value passed to the function.
There is a misconception here with what const means, probably because it's a little confusing that this works:
const int SIZE = 20;
int array[SIZE];
but this doesn't:
void foo(const int SIZE) {
int array[SIZE];
// ...
}
const int SIZE = 20;
foo(SIZE);
The issue is that the array size in an array declaration must be a core constant expression. Simplified, that means an expression that's evaluatable at compile time to be a constant. That is true in the first case (you can see that SIZE is the integral constant 20) but that is not true in the second case. There, the SIZE function parameter is just const - in the sense that it is nonmodifiable - and not a core constant expression. You can see the difference in that I can call foo() with something that is clearly unknowable until runtime:
int x;
if (std::cin >> x) {
foo(x);
}
In order to pass an argument into foo, and have that argument be used as an array bound, it is not enough to have it be const - the actual integral value must be encoded into the type (unless you call foo() as constexpr which I'm assuming is not the case here). In which case, you'd have to do something like:
template <int SIZE>
void foo() { ... }
const int SIZE = 20;
foo<SIZE>();
or:
template <int SIZE>
void foo(std::integral_constant<int, SIZE > ) { ... }
const int SIZE = 20;
foo(std::integral_constant<int, SIZE>{} );
or simply have SIZE be a global constant or otherwise accessible to foo() in a way that doesn't have to do with its arguments.
Or, there's always the simple option: use std::vector:
void foo(const int SIZE) {
std::vector<int> v(SIZE);
...
}
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
Option 1
Instead of defining SIZE in main, add a constexpr function. Use the constexpr function instead of passing the size.
constexpr int getSize()
{
return 20;
}
int* Mode(int* numbers, int & mode)
{
int occurences[getSize()];
// ...
}
Option 2
Use std::vector instead of array.
int* Mode(int* numbers, int & mode, int size)
{
std::vector<int> occurences[size];
// ...
}
Option 3
Use a function template.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
int occurences[SIZE];
// ...
}
Option 4
Use a function template and std::array.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
std::array<int, SIZE> occurences;
// ...
}
You're confusing things. A constant expression has nothing to do with const (at least not that much) ;).
let's think we are the compiler and face this function:
void foo(const int SIZE) { }
The constmerely says "we are not able to change the function-local variable SIZE inside the function body.
We need to compile it without assuming that SIZE is compile time constant. Why?
Because there is noone stoping us from doing something like:
int i{};
std::cin >> i;
foo(i);
You can pass any (matching/convertible) value to a by value const function argument.
What should happen when the compiler assumed the value passed to foo was a compile time constant expression?
If you want to pass compile time constants, use templates and while you're at it use std::array instead of T[N]:
template<std::size_t N>
void foo()
{
std::array<int, N> occurences;
}
const isn't doing what you think it's doing in your Mode function.
When const is used in function definition, const is simply telling the compiler that the function will not change the argument declared const inside of the scope of it's function. But that does not make the argument a constant, it is actually called a constant expression. Some compilers enforce this, others do not, and so will allow you to change const expressions (arguments passed with const keyword).
In order to use a globally accessible constant value which you can use, like SIZE, you'll need to declare a global constant before the function is called; which could be declared outside of main(), or at least outside the scope of all other functions but main(), if you must declare all inside main. Pass the global constant to the Mode function just as you would any other variable.
Oh, and, main() needs a return type.
I've edited the code to meet your specific constraints.
Here is a variation on your original code:
int main(){
//Declare constants first.
const int SIZE = 20; /*Could declare here instead.*/
//Declare variables next.
int *intPtr = 0; // to hold the pointer passed from Mode.
int *numbersPointer = 0;
int mode = 0;
//Define Mode (using OP's code.)
int* Mode(int* numbers, int & mode, const int size){
int occurences[size];
// Calculate mode
}
/*Now use constants, variables, and functions.*/
intPtr = Mode(numbersPointer, mode, SIZE); //Call mode.
return 0;
}
This code will not compile:
#ifndef RemoteControl_h
#define RemoteControl_h
#include "Arduino.h"
class RemoteControl
{
public:
RemoteControl();
~RemoteControl();
static void prev_track();
static void next_track();
static void play_pause_track();
static void mute();
static void vol_up();
static void vol_down();
void respond(int code);
void add_code(int code, void (*func)());
private:
boolean active = true;
struct pair {
int _code;
void (*_func)();
};
const int max = 1000;
int database_length = 0;
pair database[max]; //This line doesn't compile unless I use a literal constant instead of "max"
};
#endif
But if I put the section below in the constructor for the class instead it works fine.
const int max = 1000;
int database_length = 0;
pair database[max];
Am I not allowed to declare an array within a class in c++ and use a virtual constant as the length? I am working in arduino if that makes a difference, but I expect that I am not understanding something with the c++ language since this is a standard .h file. Oh and the problem isn't the .cpp file because I completely removed it with the same results: compiles with literal constant length but not virtual constant length.
In C or C++,try using malloc() in stdlib.h, cstdlib for c++. Don't forget free()
const int max = 1000;
struct pair *ptr = malloc(sizeof(pair) * max); // allocated 1000 pairs
free(ptr); // when the amount of memory is not needed anymore
Let me first clear a few things up for you.
In C, a const variable is considered as const-qualified, it is not a compile-time constant value (unlike an integer literal, which is a compile time constant value). So, as per the rules for normal array size specification, you cannot even use a const variable in this case.
In C, we may have the provision to use VLA which enables us to use syntax like pair database[max] even if max is not a const variable but that is again some optional feature of the compiler (as per C11).
In C++, we can use a const variable as the size of array, as in C++, a const variable is a compile time constant.
So, to answer your question:
In C, your code will be ok if your compiler supports VLA. and even if max is not const.
In C++, there is no VLA, but it maybe supported as a gnu extension. If max is const, it will be ok.
The easiest fix is to just take the
const int max = 1000;
out of the class and put it above the class.
Even better would be to ensure that it is a compile-time constant like so:
constexpr int max = 1000;
I have a global array, which is indexed by the values of an enum, which has an element representing number of values. The array must be initialized by a special value, which unfortunately is not a 0.
enum {
A, B, C, COUNT
};
extern const int arr[COUNT];
In a .cpp file:
const int arr[COUNT] = { -1, -1, -1 };
The enum is occasionally changed: new values added, some get removed. The error in my code, which I just fixed was an insufficient number of initialization values, which caused the rest of the array to be initialized with zeroes. I would like to put a safeguard against this kind of error.
The problem is to either guarantee that the arr is always completely initialized with the special value (the -1 in the example) or to break compilation to get the developers attention, so the array can be updated manually.
The recent C++ standards are not available (old ms compilers and some proprietary junk). Templates can be used, to an extent. STL and Boost are strongly prohibited (don't ask), but I wont mind to copy or to reimplement the needed parts.
If it turns out to be impossible, I will have to consider changing the special value to be 0, but I would like to avoid that: the special value (the -1) might be a bit too special and encoded implicitly in the rest of the code.
I would like to avoid DSL and code generation: the primary build system is jam on ms windows and it is major PITA to get anything generated there.
The best solution I can come up with is to replace arr[COUNT] with arr[], and then write a template to assert that sizeof(arr) / sizeof(int) == COUNT. This won't ensure that it's initalized to -1, but it will ensure that you've explicitly initialized the array with the correct number of elements.
C++11's static_assert would be even better, or Boost's macro version, but if you don't have either available, you'll have to come up with something on your own.
This is easy.
enum {
A, B, C, COUNT
};
extern const int (&arr)[COUNT];
const int (&arr)[COUNT] = (int[]){ -1, -1, -1};
int main() {
arr[C];
}
At first glance this appears to produce overhead, but when you examine it closely, it simply produces two names for the same variable as far as the compiler cares. So no overhead.
Here it is working: http://ideone.com/Zg32zH, and here's what happens in the error case: http://ideone.com/yq5zt3
prog.cpp:6:27: error: invalid initialization of reference of type ‘const int (&)[3]’ from expression of type ‘const int [2]’
For some compilers you may need to name the temporary
const int arr_init[] = { -1, -1, -1};
const int (&arr)[COUNT] = arr_init;
update
I've been informed the first =(int[]){-1,-1,-1} version is a compiler extension, and so the second =arr_init; version is to be preferred.
Answering my own question: while it seems to be impossible to provide the array with the right amount of initializers directly, it is really easy to just test the list of initializers for the right amount:
#define INITIALIZERS -1, -1, -1,
struct check {
check() {
const char arr[] = {INITIALIZERS};
typedef char t[sizeof(arr) == COUNT ? 1: -1];
}
};
const int arr[COUNT] = { INITIALIZERS };
Thanks #dauphic for the idea to use a variable array to count the values.
The Boost.Preprocessor library might provide something useful, but I doubt whether you will be allowed to use it and it might turn out to be unwieldy to extract from the Boost sources.
This similar question has an answer that looks helpful:
Trick : filling array values using macros (code generation)
The closest I could get to an initialization rather than a check is to use a const reference to an array, then initialize that array within a global object. It's still runtime initialization, but idk how you're using it so this may be good enough.
#include <cstring>
enum {A, B, C, COUNT};
namespace {
class ArrayHolder {
public:
int array[COUNT]; // internal array
ArrayHolder () {
// initialize to all -1s
memset(this->array, -1, sizeof(this->array));
}
};
const ArrayHolder array_holder; // static global container for the array
}
const int (&arr)[COUNT] = array_holder.array; // reference to array initailized
// by ArrayHolder constructor
You can still use the sizeof on it as you would before:
for (size_t i=0; i < sizeof(arr)/sizeof(arr[0]); ++i) {
// do something with arr[i]
}
Edit
If the runtime initialization can never be relied on you should check your implementation details in the asm because the values of arr even when declared with an initializer may still not be known at until runtime initialization
const int arr[1] = {5};
int main() {
int local_array[arr[0]]; // use arr value as length
return 0;
}
compiling with g++ -pedantic gives the warning:
warning: ISO C++ forbids variable length array ‘local_array’ [-Wvla]
another example where compilation actually fails:
const int arr1[1] = {5};
int arr2[arr1[0]];
error: array bound is not an integer constant before ']' token
As for using an array value as a an argument to a global constructor, both constructor calls here are fine:
// [...ArrayHolder definition here...]
class IntegerWrapper{
public:
int value;
IntegerWrapper(int i) : value(i) {}
};
const int (&arr)[COUNT] = array_holder.array;
const int arr1[1] = {5};
IntegerWrapper iw1(arr1[0]); //using = {5}
IntegerWrapper iw2(arr[0]); //using const reference
Additionally the order of initalization of global variables across different source files is not defined, you can't guarantee the arr = {-1, -1, -1}; won't happen until run time. If the compiler is optimizing out the initialization, then you're relying on implementation, not the standard.
The point I really wanna stress here is: int arr[COUNT] = {-1, -1, -1}; is still runtime initialization unless it can get optimized out. The only way you could rely on it being constant would be to use C++11's constexpr but you don't have that available.
If I want to declare a dynamic size array in the main function, I can do:-
int m;
cin>>m;
int *arr= new int[m];
The following cannot be done as while compiling the compiler has to know the size of the every symbol except if it is an external symbol:-
int m;
cin>>m;
int arr[m];
My questions are:
Why does the compiler have to know the size of arr in the above code? It is a local symbol which is not defined in the symbol table. At runtime, the stack takes care of it(same way as m). Is it because the compiler has to ascertain the size of main() (a global symbol) which is equal to the size of all objects defined in it?
If I have a function:
int func(int m)
Could I define int arr[m] inside the function or still I would have to do
int *a= new int[m]
For instance :
int MyArray[5]; // correct
or
const int ARRAY_SIZE = 6;
int MyArray[ARRAY_SIZE]; // correct
but
int ArraySize = 5;
int MyArray[ArraySize]; // incorrect
Here is also what is explained in The C++ Programming Language, by Bjarne Stroustrup :
The number of elements of the array, the array bound, must be a constant expression (§C.5). If you need variable bounds, use a vector (§3.7.1, §16.3). For example:
To answer your questions:
1) Q: Why does the compiler have to know the size of arr in the above code?
A: If you generate assembly output, you'll notice a "subtract" of some fixed value to allocate your array on the stack
2) Q: Could I define int arr[m] i ... inside the function?
A: Sure you could. And it will become invalid the moment you exit the function ;)
Basically, you don't want an "array". A C++ "vector" would be a good alternative:
std::vector<A> v(5, A(2));
Here are a couple of links you might enjoy:
http://www.parashift.com/c++-faq/arrays-are-evil.html
http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx