I have the shortest question possible:
Why does this not work in VS2010?
string keyword("lookuptable");
const int kwSize = keyword.size();
char oldBuffer[kwSize+1];
It works perfectly in GCC. VS2010 tells me that
"expression must have constant value"
I am using Win32 console application / empty project.
I am using absolutely nothing special, just
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
using namespace std
and its a single main function in a cpp file.
The size of an array must be an integral constant expression, or ICE (which means that it must be known at compile-time). You can use a const int in an ICE, but only if its initializer is itself an ICE.
A function call, like keyword.size() is not usable in an ICE, so kwSize is not usable in an ICE.
If it "works perfectly" in gcc it is either due to a bug or a language extension of some sort.
In C++0x, some function calls can be used in integral constant expressions, but they must be constexpr functions and there are restrictions on their use. To the best of my knowledge, no compiler fully supports constexpr yet. In any case, std::string::size is not constexpr.
GCC has a language extension allowing variable-length arrays. Visual C++ does not. You must initialize stack-based arrays with a fixed, compile-time constant.
As others have mentioned, non-constant array bounds are a GCC extension (likely a side benefit of its C99 support - C99 does allow non-constant array bounds). If you want this in C++, you should use a vector:
std::vector oldBuffer(kwSize + 1);
To turn this into a char *, do:
&oldBuffer[0]
This, while not strictly speaking valid C++ prior to C++0x, works properly in every compiler I've come across so far. C++0x retroactively blesses this usage, and also provides a oldBuffer.data() equivalent.
the answer is there "expression must have constant value". The const has to be something resolved at the compile time.
keyword.size() is evaluated at runtime therefore it is not a compile time constant. Depending on the compiler it may not be allowed to use an array size that is depending on some runtime value.
Some further info about variable array length in gcc
Related
According to
C++ : Creating an array with a size entered by the user
creating arrays with runtime bounds is not allowed in c++.
But I get below code compiled without errors.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin>>n;
int a[n][n];
a[n-1][n-1]=9;
cout<<a[n-1][n-1]<<endl;
return 0;
}
and it works fine too. check it here ->
http://cpp.sh/6bies
Can someone help to solve this confusion?.
Is creating arrays with runtime bounds allowed in c++?
Such arrays are ill-formed.
But I get below code compiled without errors. ... and it works fine too.
The C++ standard does not disallow compilers from successfully compiling ill-formed programs. It is sufficient to show a diagnostic message. This allows compilers to extend the language.
If you take a look at the compiler output of your example, you'll find that the compiler did tell you about it, as is required by the C++ standard:
15:15: warning: array of array of runtime bound [-Wvla]
So, it appears that your compiler supports arrays of runtime bound - and even arrays of arrays of runtime bound - as a language extension.
Most compilers can be asked to refuse programs that are ill-formed according to C++ standard, if you so prefer.
It is standard compliant to create arrays of runtime bound in dynamic storage. The simplest way is to use std::vector.
If you are using gcc, it has some extensions, one of them being support for variable length arrays (VLA) that is available in C99.
I am doing the following for initializing an array in c++
int a;
cin>>a;
float b[a];
This works and compiles in my computer. IS this correct? I thought that we can only do this if a was a const int.
Depends on you definition of "correct".
This is called variable-length array (or just VLA) and it's not officially supported in the current versions of C++ (100% sure for C++03 and before, 99.99% sure for C++11), but it is in C.
Some compilers allow this as a compiler extension.
It's not about whether a is a constant int. It's about whether a has a initial value assigned at comipling time. Compiler needs to allocate storage according to a const int value. C++ standard doesn't support variable length array right now.
In C99, this syntax of variable length array is valid, but C++ standard says no. It is a very useful feature, leaving all the hairy memory allocating stuff to the compiler.
In GCC and Clang, this feature is supported as a compiler extension, so you won't get any warning and error. But MSVC compiler will put an error message that says cannot allocate an array of constant size 0, So it is compiler specific.
The compiler that supports this feature may have convert your code with new operator.
int a;
cin>>a;
float *b = new float[a];
This is valid in C++ standard.
Another thing is that though it is called variable-length array, it is not length-variable at all. Once it is defined, its length is a constant value which never change. You can't expand it or shrink it.
It is much better to use the vector container which is truly length variable, and with much more scalability and adaptivity.
See the post for more discussion on Why aren't variable-length arrays part of the C++ standard?
Can C++11 compilers (and do they) notice that a function is a constexpr and treat them as such even if they are not declared to be constexpr?
I was demonstrating the use of constexpr to someone using the example straight from the Wikipedia:
int get_five() {return 5;}
int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++
To my surprise the compiler was OK with it. So, I further changed get_five( ) to take a few int parameters, multiply them and return the result while still not being explicitly declared to be constexpr. The compiler was OK with that as well. It seems that if the compiler can do this there isn't much point to having the restrictions that are required in order to explicitly declare something constexpr.
On a properly-functioning C++11 compiler, your code would be rejected.
Based on its being accepted, you're almost certainly using gcc (or something that closely emulates its bugs). gcc [depending somewhat on flags] can accept array sizes that aren't constant by any measure (e.g., depend on run-time input from the user) because they support an analog of C99 variable-length arrays in C++.
GCC, as of GCC 12, supports the -fimplicit-constexpr command-line toggle which enables exactly that, for methods marked as inline.
Changelog: https://gcc.gnu.org/gcc-12/changes.html
Patch with some rationale and discussion: https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=87c2080b
A compiler can detect whether or not a function could have been declared with constexpr even when they haven't, for optimization purposes (i.e. computing the result of a function at compile-time). Compilers did that prior to C++11.
But for use in places that requires constant expressions, such as template parameters of integral type, it is against the standard to allow calls to functions that are not declared with the constexpr keyword.
When I use the constant argument of a function as a array size in C++ it gives "Constant expression required" error:
So the compiler is not considering m as a constant object, this means I can change the value of m inside the function, but when I try to increment the value of m it gives "cannot modify a const object" error:
It is really ambiguous to me. Can anyone please explain what I'm getting wrong?
const doesn't actually mean "this value is constant", but, "you cannot change this value."
With this, it should be clear why the latter code fails to compile but the former cannot. Even though you give it a default of 5, that doesn't guarantee it's five, and so you don't have a constant, so you can't make an array. But the type is still const, so you can't change it.
That said, since C99 you can have variable-length arrays so this would actually be fine. (It is not okay in C++.) Your compiler just seems to be too old to support C99. (I highly recommend using the latest GCC.)
You cannot create statically a variable-sized array. That is what malloc() is for. The compiler treats the constants as a variable even if they are delclared as const, because it knows nothing about them at compile time, so it can't produce compile-time code to create a static array.
Furthermore: if you declare m as const int m=5, why on Earth do you expect it to be able to increment? It's a constant, so you cannot possibly modify its value.
Nothing is ambigous here, you have just to think a bit about it.
CodeBlocks is an editor/IDE, not a compiler. I assume it uses GCC for a compiler, which I think has an extension to use C99's variable-length arrays in C++.
This is not even in C++11 (and probably never will be in C++, since we have std::vector), so this is one of the very few cases where a 20 year old compiler actually got it right.
If I was you, though, I'd still dump TC++. It belongs into a museum.
You need a compile-time constant integral expression. Not just a const.
I have been teaching myself programming for couple of years, and I was sure that if you need array declaration of a variable number you need to use malloc or new.
Today I found that this compiles under g++ version 4.4.4, without warnings or errors:
#include <iostream>
using namespace std;
int main()
{
int size_array;
cin >> size_array;
int iTable[size_array];
for(int i=0;i < size_array;i++)
iTable[i]=i*i;
for(int i=0;i < size_array;i++)
cout << iTable[i] << endl;
return 0;
}
Also it compiles completely fine if you are using gcc (after changing cout and cin with printf and scanf)
Under Visual Studio this code fails to compile since size_array is not constant.
When this was changed? This is a safe method?
This is a C99 feature - VLA - which is not a part of standard c++. You can use it if your compiler supports it and you don't require portability. If the compiler supports it, it's perfectly safe to use - but it's a bad habit using non-standard features.
This is a compiler extension of gcc, not standard.
No thats not safe at all. It could corrupt your stack.
See http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.20.
Simply put, in C99, this is called VLA and is part of the standard (correct me if I'm wrong) but in C++ this is not part of the standard. If you need this functionality use std:vector instead.
This depends if you are writing C or C++. I'll assume C as for c++ you would be better off using std::vector rather than an array.
In C it depends which versiuon you are using. If and only if you are using a C99 standard compiler then the array can take its size from a variable at run time as you do here otherwise the size must be defined at compile time. Visual Studio does not support the dynamic array - see MSDN
C++ uses the C89 standard so requires the size to be set at compile time.
So in your case you need to see what flags you passed to the compiler.
As noted by #Eric the code is C++ so the working compiler is using a non standard extention so for gnu I would add flags to enforce a standard e.g. -ansi or -std=c++98 and -pedantic
There is an extension of GCC mimicking C99 Variable Length Arrays. It's not standard C++.
However, even if you have this turned off, the posted code can compile. The standard does not require a diagnostic for this case: it's Undefined Behaviour, not an error.
In really obvious cases a compiler may choose to prevent you from writing this, but otherwise it is free to let you fail in peace.
Conclusion: don't be fooled by the compilation. It's still bad and wrong.
You can get this functionality in C or C++ with alloca (_alloca on Windows). std::vector is NOT a substitute: it is allocated on the heap, with new, which calls malloc, which is potentially expensive.
There is a good reason why you might want to have an array whose length is determined at runtime allocated on the stack: it's really fast. Suppose you have loop that executes frequently but has an array that depends on something at runtime (say, the size of your canvas widget). You can't just hard-code a number: your program will crash when we all get 36" 300 dpi Retina-display monitors and pixels[2400] is no longer safe. But you don't want new, or your loop hits a malloc and gets slow.
Although, for large arrays, it might be better to have a std::vector that is static to the function an only gets resized (larger) when necessary since your stack has limited size.
(See http://msdn.microsoft.com/en-us/library/wb1s57t5(VS.71).aspx)
It's okay to use the feature if you are using c99.
You have to be very careful about the value of size. a large value will overflow your stack, and your process may go insane.