I was just wondering why this works in Clang 4.0:
unsigned cnt = 42;
int k[cnt];
But this won't:
unsigned cnt = 42;
string bad[cnt];
I just checked C++ primer 5th edition. It says that:
the dimension must be known at compile time, which means that the
dimension must be a constant expression
If that's true, why does the int k[cnt]; work?
Neither snippet works in C++.
However, in C, it's possible to use non-constant expressions as array sizes. Some compilers (for example, GCC without -pedantic option) support that C feature in C++ code.
As for the difference between element types, it's compiler-specific. GCC compiles both. clang++ prohibits non-POD types (such as std::string) in this case.
What compiler are you using, I am using gcc and both const and nonconst works fine.
It is not a matter of c, arrays are not meant to be defined through variables, only macros and const expressions.
It's a matter of compiler's interpretation, I doubt it is related to standards.
Is clang 4.0 actually apple xcode clang? i think that is actually version 3.1. clang offers a nice explanation itself:
warning: variable length arrays are a C99 feature
[-Wvla-extension]
int k[cnt];
Related
I'm just jumping into C++, coming from C
In C (89/90), a const is not actually a constant (as opposed to a #define'd, enum, or literal), but rather read-only once set. I.e, I can:
const int x = rand();
and that's fine - the point being x isn't known until runtime. Hence, I can't
int arr[x]; // error - x is not a compile-time constant
Then, one of the C standards (99?) went ahead and allowed for variable-length arrays. Although I normally code against the ANSI standard in C, this has actually had an impact now that I am trying to pickup C++11.
As far as I know, C++ does not allow for variable-length arrays. However, many compilers allow it as an extension (GCC ?). The problem is, now that I am trying to learn C++11, I can't tell if what I'm coding is valid C++, or C++ extended with C99-compatibility. Ex:
std::default_random_engine e{};
std::uniform_int_distribution<int> d{};
const int x{d(e)};
int arr[x]; // compiles
I can't tell if this is valid C++ or not. Clearly, the value of x is not known until runtime. I think I may not understand the difference between C and C++ const?
You are correct VLAs are a C99 feature(optional in C11) and the C++ standard does not include this feature although both gcc and clang allow them in C++ as an extension. We can see they are not allowed by going to the draft C++11 standard section 8.3.4 Arrays which says:
D1 [ constant-expressionopt] attribute-specifier-seqopt
^^^^^^^^^^^^^^^^^^^^^^
For both gcc and clang using the -pedantic flag will warn when you are using an extension. If you are targeting C++11 then you should also specify that using -std=c++11. You can use -pedantic-errors to turn the warning into errors. If you compile your code using -pedantic you should see the the following warning:
warning: ISO C++ forbids variable length array 'arr' [-Wvla]
int arr[x]; // compiles
^
gcc documents their support for various standards, defaults and flags to enforce standard on their Language Standards Supported by GCC page and it says:
to obtain all the diagnostics required by the standard, you should
also specify -pedantic (or -pedantic-errors if you want them to be
errors rather than warnings).
In general clang supports what gcc does but you can find more details on their Language Compatibility page.
Note as mentioned by GingerPlusPlus std:vector is considered the alternative for VLA in C++.
I'm a newb at C++ and I practice coding on my school computer, so I have to use an online compiler (www.CompileOnline.com). I have a variable that is defined by a function and is then used to initialize an array like so:
int var = function(a);
int num[var];
This code works just fine on the website, but on Visual Studio Express 2012 it gives me an error:
C2057: expected constant expression
Is this a problem with Visual Studio? I've read that it's a C++ rule, but then why does it work on the website? Any help is appreciated, thanks.
The feature that the code snippet requires is called variable length arrays (VLAs). Support for this feature in the C or C++ language depends on the compiler and the version of the standard.
C99 supports VLAs as standard.
Versions earlier than C99 (includes C90) do not support VLAs as standard, but some compilers may implement it as a language extension.
C11 makes VLAs an optional feature.
C++14 supports a restricted variant of VLAs called dynamic arrays.
Versions earlier than C++14 (includes C++11, C++03, and C++98) do not support VLAs as standard, but some compilers may implement it as an extension.
In particular, GCC implements VLAs as a language extension for C90 and C++, and apparently www.compileonline.com uses GCC as the compiler (version 4.7.2 as of this writing). No version of the Visual C++ compiler implement VLAs.
Herb Sutter talks about C++14's dynamic array feature:
In the language, draft C++14 now allows stack-based arrays to have a size determined at run time:
void f(std::size_t n)
{
int a[n];
...
}
Note that this is not the same as C99 variable length arrays (VLAs),
and that the C11 standard has made VLAs conditionally-supported so
that they are no longer part of portable C required in a conforming C
compiler. In particular, C++ explicitly not does support the following
features from C99 VLAs which C++ feels are not desirable:
multidimensional arrays, where other than the top level has a runtime
bound (in analogy, the array form of new expressions doesn’t support
that either)
modifications to the function declarator syntax
sizeof(a) being a runtime-evaluated expression returning the size of a
typedef int a[n]; evaluating n and passing that through the typedef
If you want C++ code that works in pretty much any version of C++, consider using std::vector instead:
#include <vector>
int main()
{
int var = function(a); // Assume function() has been defined.
std::vector<int> num(var); // Creates a vector with var number of elements.
// ...
int num1 = num[1]; // You can access elements in vectors just like arrays.
num[1] += 10;
// ...
}
Variable length arrays are not allowed in C++. The size of the array must be determinable at compile time.
CompileOnline.com says it uses GNU GCC version 4.7.2. GCC has an extension that supports variable length arrays in C++:
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++.
It seems the online compiler is gcc which implement variable length arrays as an extension in C++. The "problem" in this case is actually gcc, not VC++: gcc implement an extension which enables by default, tricking users into creating non-portable code.
If you need a variable sized array in C++, you'd include <vector> and use the class template declared in this header, e.g.:
int var = function(a);
std::vector<int> num(var);
Is this valid in C language?
#include <stdio.h>
int main()
{
int i = 5;
int a[i]; // Compiler doesn't give error here. Why?
printf("%d",sizeof(a)); //prints 5 * 4 =20. 4 is the size of integer datatype.
return 0;
}
Compiler doesn't give error at the statement int a[i];. i isn't a constant then how can it compile successfully? Is it because I am using gcc compiler? Is it allowed in C++?
Yes, this is valid as of C99, and is called a variable-length array (VLA). In other words, it has been in an official language standard for around 14 years.
No, it's not valid in C++, see this question for details.
Also note that sizeof is not a function, so that can be written as printf("%zu\n", sizeof a); which also uses the proper format specifier for a size_t value.
This is valid C99 it is called Variable Length Array(VLA) gcc supports VLA as an extension outside of C99 mode with respect to C++ both gcc and clang support variable length arrays as an extension even though this is really a C99 feature.
You can build using the -pedantic argument in gcc and clang both will give a warning similar to the following:
warning: variable length arrays are a C99 feature [-Wvla-extension]
sizeof is expected to work correctly with VLA although it will be evaluated instead of an integer constant. Although you do have undefined behavior in your code since you specified the wrong format specifier for size_t which is zu and not d. The C99 draft standard in section 7.19.6.1 The fprintf function which printf's section refers back to for the format string paragraph 9 says:
If a conversion specification is invalid, the behavior is undefined.[...]
I'd just add to unwind's answer that in C++14, there will be runtime-sized arrays, which work pretty much the same as VLA.
See chapter 8.3.4 in N3690 (array of runtime bound of T)
They seem to be supported in clang-3.3 (in C++1y mode), but NOT in GCC 4.8 (the support should come in GCC 4.9).
When you write the code in pre-C++14 mode (c++03, c++11), your code will probably compile, but it should issue a warning about using a C99 feature not supported in C++.
And you always should compile with most pedantic warnings enabled :)
Sizeof operator is compiler independent.
You could read more about this in the following links ::
VLA-as-function-argument
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.
I want to play with constexpr, does any compiler support it yet?
The Apache Stdcxx project has a nice table detailing which C++0x features are supported by which compilers. It's been updated on a regular basis and covers most of the modern C++ compilers.
According to that, only GCC 4.5 supports constexpr (note that that support may be experimental).
Between that list and what has been said in the comments, it appears the answer is "no."
As of July 2011, gcc 4.7 supports constexpr. You need to build it from svn though.
Agreed, g++ 4.5 and 4.6 support the keyword, but ignore the implications. I just compiled a simple factorial program (on both versions using -std=c++0x) with the line:
constexpr fact(int i) { return (i>1) ? fact(i-1)*i : 1; }
and it compiled and ran but when examining the asm source (-S option) it showed the function was called with the parameter instead of being determined by the compiler.
Usage of "constexpr" is really easy. Look at this piece of code:
constexpr int get_five(){
return 5;}
This function returns always 5, so it can be declared with "constexpr" keyword.
But factorial function returns value depending on argument, so its "output" is not always the same.