Why can't we initialize array size using non-const size in global area....outside main() ....
//outside main - global
int val=5;
int arr[val];
int main()
{
}
this gives error
7:12: error: array bound is not an integer constant before ']' token
In function 'int main()':
But if i move this same code inside main/body of function error disappears....
there is no error and it compiles fine...
int main()
{
int val=5;
int arr[val];
}
Also this works fine inside body of a function
void fn(int val)
{
int arr[val];
}
int main()
{
fn(5);
}
Confused and how does moving array size can't be intialized only outside main?
The first sample, at file scope
int val=5;
int arr[val];
int main()
is illegal on both C and C++. Variables at file scope must be defined (created) before their first use, and continue to exist until the program ends - which also means that, once created, an array cannot be resized. In the case of arrays, this means (among other things) that their dimension must be known at compile time. Using a variable as an array dimension runs afoul of the need for the size of a static to be known at compile time - for example, the value of val could be changed at run time (e.g. in main()) which will be AFTER arr is created.
The second example
void fn(int val)
{
int arr[val];
}
is legal in C (from 1999), because arr is of automatic (not static) storage duration. It will be created when the function body is entered, and cease to exist when the function returns. This is called a "variable length array" or VLA, because the number of elements is determined by a value of a variable (val) at run time.
VLAs were also not supported before the 1999 C standard.
In C++, VLAs are illegal. Period. However, some C++ compilers do support such a feature as a non-standard extension. In C++, rather than using arrays, a standard container (e.g. std::vector<int>) is preferred for various reasons, including ability to resize it at run time.
For the array inside function:
you are relying on GCC extension, if you add -pedantic you will get this warning:
warning: ISO C++ forbids variable length array 'arr' [-Wvla]
So C++ does not support variable length arrays, suggested alternative is std::vector.
For the array outside function:
you need to add const before int. Yes I know compiler could in theory figure out that val is never changed, but for some reason(nobody thought to add that to standard, or there are good reasons not to do it) you are required to add const.
Related
I know that when I do this
int x;
cin >> x;
char arr [x];
it is ill fomed according to c++ standard since c++ does not allow static arrays of variable size.
My question is, if I declare static array in function scope with variable size from function parameter is it still ill formed? Or is it well defined in the standard?
void foo(int size)
{
char arr [size];
// do something
}
void main()
{
foo(10);
foo(20);
}
For starters you have no "static arrays". The arrays used in your examples have automatic storage duration. And C where variable length arrays are allowed requires that such arrays had automatic storage duration.
Variable length arrays are not a standard feature of C++.
Instead use the standard container std::vector. Or if you are using strings then use the standard class std::string.
For example
#include <iostream>
#include <string>
void foo(int size)
{
std::string s;
s.resize( size );
}
int main()
{
foo(10);
foo(20);
}
This is not a valid C++ code:
char arr [size];
It may work on some compilers which has support of variable size array of C as an extension.
The array also is not static it is automatic in your case if size was constant known at compile time.
It is not valid anywhere neither function scope nor anywhere else.
You can use std containers such as vector which has support for variable size or even std::string.
When foo is called, a new stack frame is pushed on the stack which reserves just enough space for all the local variables in the scope of foo to fit. If another function bar were to be called from within foo, its stack frame would be pushed on top of foo's. For this to work (efficiently), the size of the stack frame (by extension all local variables in foo, including the array arr) must be known to the compiler.
When the functions return (first bar, then foo) their stack frames are popped in reverse order of their creation, and thus the stack memory remains defragmented at all times and the location of each and every local variable is determined at compile time, hence the relative efficiency. Heap memory can have a dynamic size but this comes at the cost of having to allocate a suitably sized spot on the heap.
You can also see this dichotomy in the standard library containers std::vector and std::array. std::array is effectively just a wrapper around C-style arrays and thus its size needs to be known at compile time and is therefore specified as a template parameter, e.g. std::array<char, 42> wraps char[42]. Unlike in your case, the compiler will (rightly) complain if you use a runtime variable as the second template parameter. You can however safely use any constant expression (e.g. result of a constexpr function).
double rainPerMonth(const int YEARS)
{
int monthYear[MONTHS][YEARS];
// ...
}
Visual Studio shows a squiggly line underneath the array declaration, saying that YEARS must be a constant when I'm creating the array. Is this an IDE issue because the variable has yet to be initialized, or am I writing this incorrectly?
MONTHS is already declared globally.
An array size must be a constant expression - that is, a value known at compile time. (Some compilers offer C-style variable-length arrays as a non-standard extension, but I don't think Visual C++ does. Even if it does, it's better not to rely on such extensions.)
A function argument isn't known at compile time, so can't be used as an array size. Your best option is here is probably
std::vector<std::array<int, MONTHS>> monthYear(YEARS);
In C++, an array must be sized at compile time. What you are attempting to do is declare one that is sized at runtime. In the function you've declared, YEARS is only constant within the scope of the function. You could call it rainPerMonth(someInt); where someInt is the result of some user input (which shows you that the result is not a compile-time constant).
Variable Length Arrays are an extension to C, but not C++. To do what you want, you can use dynamic memory, or a std::vector.
I think your problem lies in the fact that C++ wants a constant in the sense of compile-time constant to create your variable monthYear. If you pass it as a function, it need not be known at compile time? For example:
const int x=2;
const int y=3;
char xyChoice;
std::cin >> xyChoice;
if (xyChoice == 'x')
rainPerMonth(x);
else
rainPerMonth(y);
I'm unsure, but it seems to me like this would give you a constant int being passed to your function, but the compiler wouldn't know what size to create an array for before runtime?
I am not completely sure why this isn't working
void foo(const int a=10){
const int b = 10;
int c[a];
int d[b];
}
I thought that I say to the compiler the a is constant - I even tell it that default value is 10 :).
Why is he yelling:
1>sum_floats_txt.cpp(105): error C2057: expected constant expression
1>sum_floats_txt.cpp(105): error C2466: cannot allocate an array of constant size 0
1>sum_floats_txt.cpp(105): error C2133: 'c' : unknown size
I know what it tells me, but I do not know how to do what I want to do:
- function with static array inside of size dependable on outside constant
The function is counting something and returning the time spended on the execution (doing it in RTOS).
So I want to call this function with different parameters from main. To find out for which parameter it executes the shortest.
Is the problem in the way the static arrays works? It must have a constant size in the time of compilation. So for different static arrays I must define more of them.
Possible solution is to create more functions or more static arrays with different sizes predefined. And call them one after the other, but there are thousands of different sizes.
I do not want to do the non-automatized iteration to get the best parameters! Could arguments from main passed to the function before execution help?
VS2010 + RTX64 2013 (should not be the problem)
win7
thanks!
Don't mix up const qualified and constant.
const qualified just says that you don't have the right to modify the variable.
In C++ if a const qualified variable is also a compile time constant, the construct that you are using would be allowed. Here it is a parameter to a function, so there is no way that the compiler may know a value that it would substitute at compile time.
In C, things are different. In modern C, that is C since 1999, variable length arrays with such values that are only known during execution are allowed. Unfortunately there are still C compilers that don't conform to C99. AFAIR micorsoft compilers are among these.
The const int a argument is "read only" argument. It is not necessarily a value that the compiler knows at compile time. You can use a template argument though.
template <int N = 42>
void foo() {
int myArray[N];
}
C however does allow what you wrote there, C++ doesn't but will in C++14 with "std::dynarray".
I'm trying to do something like this:
const int array_size = 5;
string stuff[array_size];
My compiler won't let me compile this, even though array_size is a constant. Is there a way to do this without dealing with dynamic arrays?
Edit: "error C2057: expected constant expression"
I have answered this question assuming you are either coding in C or C++. If you are using a different language, this answer doesn't apply. However, you should update your question with the language you are trying to use.
Consider the following program:
int main () {
const int size = 5;
int x[size];
return 0;
}
This will compile in both C++ and C.99, but not C.89. In C.99, variable length arrays were introduced, and so locally scoped arrays can take on a size specified by a variable. However, arrays at file scope in C.99 cannot take a variable size parameter, and in C.89, all array definitions have to have a non variable size.
If you are using C.89, or defining a file scope array in C.99, you can use an enum to name your constant value. The enum can then be used to size the array definition. This is not necessary for C++ however, which allows a const integer type initialized by a literal to be used to size an array declaration.
enum { size = 5 };
int x[size];
int main () { return 0; }
#define array_size 5
string stuff[array_size];
You can use e.g. a vector or the new keyword to allocate memory dynamically, because declared arrays can not have runtime sizes.
Only thing I can think of is that you defined another array_size variable in your code, which is not a compile time constant and hides the original array_size.
array_size is not treated as a compile time constant. Constness added just makes sure that programmer can not modify it. If tried to modify accidentally, compiler will bring to your attention.
Size of an array needs to be a compile constant. Seems like your compiler is not supporting Variable Length Array. You can #define the size of the array instead which is treated as a constant expression.
I have some concepts about the VLA and its behavior that I need to clarify.
AFIK since C99 it's possible to declare VLA into local scopes:
int main(int argc, char **argv)
{
// function 'main' scope
int size = 100;
int array[size];
return 0;
}
But it is forbidden in global scopes:
const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++
int main(int argc, char **argv)
{
int local_size = 100;
int local_array[local_size];
return 0;
}
The code above declares a VLA in C99 because the const modifier doesn't create a compile-time value. In C++ global_size is a compile-time value so, global_array doesn't become a VLA.
What I need to know is: Is my reasoning correct? Is the behaviour that I've described correct?
I also want to know: Why are the VLA not allowed in global scope? are they forbidden both in C and C++? Why is the behavior of arrays into global and local scope different?
Yes your reasoning is correct, that is how these different forms of array declarations and definitions are viewed by C and C++.
As others already stated, VLA with a veritable variable length (non-const) in global scope is difficult to make sense. What would the evaluation order be, e.g if the the length expression would refer to an object of a different compilation unit? C++ doesn't have VLA, but it has dynamic initialization of objects at file scope. And already this gives you quite a head ache, if you have to rely on evaluation order.
This leaves the small gap for C concerning length expressions that contain a const qualified object, which isn't allowed. This comes from the fact that such objects are not considered "integer constant expressions" by the C standard. This could perhaps change in future versions, but up to now the C committee didn't find it necessary to allow for such a thing: there are enum constants that play that role in C. Their only limitation is that they are limited to int in C, it would be nice to also have them size_t.
C++ doesn't support VLAs, period. The reason the second code snippet works in C++ is that the const keyword creates a compile-time constant in C++; in C, it doesn't.
C99 doesn't support VLAs outside of block scope, period, regardless of how you declare the size variable. Note that C2011 makes VLA support optional.
There is a difference between being forbidden and not being allowed. ;-)
The VLA feature is designed to allow the use of stack space for a local array, to avoid the use of malloc for heap allocation. It is mostly a speed optimization.
Now you want to use VLAs outside of functions. Why? There is not much to win speedwise in avoiding a single malloc call during program start. And what stack space are we supposed to use for variables with a static life time?
I think the fundamental reason is a global variable has linkage, its size has to be known at compile time. If not, how could one link the program?
local variables have no linkage and the VLAs are allocated on the stack, which grows dynamically as the program runs.
So, for global VLA's, one of the issues (there are many variants on the theme) can be shown here:
int size;
int a;
int v[size];
int b;
....
in another file:
extern int a;
extern int b;
The linker will have to know where a and be are in relation to each other at link time, or it won't be able to fix them up correctly at load-time.