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
Related
As we already know, VLA (standardized in C99) are not part of the standard in C++.
So the code below is "illegal" in C++:
void foo(int n) {
int vla[n];
for (int i = 0; i < n; ++i) {
vla[i] = i;
}
}
Despite of that the compiler (g++ and clang++) accepts the code as valid syntax, producing just a warning in case -pedantic flag is enable.
ISO C++ forbids variable length array ‘vla’ [-Wvla]
My questions are:
Why does the compiler accept that declaration?
The compiler cannot just reject an array in which length [is-no-know-at-compile-time]?
Is there a sort of compatibility syntax rule to follow?
What does the standard say about?
From the assembly code produced I see the compiler writes in the stack
in the loop, like a normal array, but I cannot find anything about the standard behaviour.
Why does the compiler accept that declaration?
Because its authors chose to make it do so.
GCC in particular allows, by default, a lot of non-standard stuff that was historically accepted by old C compilers. They like "compatibility" in that sense.
What does the standard say about [it]?
Precisely what the warning states it says about it: ISO C++ forbids variable length arrays.
C++ does not have VLAs.
Where you see one being accepted, it is a compiler extension; to find out how that compiler implements such an extension, you would have to ask the compiler's authors (or examine its source, if applicable).
The standard requires that a conforming compiler must "issue a diagnostic" when it encounters something that is illegal. Having done that, it's free to continue to compile the code with an implementation-specific meaning. (Note that "with an implementation-specific meaning" is a polite form of "with undefined behavior").
As we already know, VLA (standardized in C99) are not part of the standard in C++.
So the code below is "illegal" in C++:
void foo(int n) {
int vla[n];
for (int i = 0; i < n; ++i) {
vla[i] = i;
}
}
Despite of that the compiler (g++ and clang++) accepts the code as valid syntax, producing just a warning in case -pedantic flag is enable.
ISO C++ forbids variable length array ‘vla’ [-Wvla]
My questions are:
Why does the compiler accept that declaration?
The compiler cannot just reject an array in which length [is-no-know-at-compile-time]?
Is there a sort of compatibility syntax rule to follow?
What does the standard say about?
From the assembly code produced I see the compiler writes in the stack
in the loop, like a normal array, but I cannot find anything about the standard behaviour.
Why does the compiler accept that declaration?
Because its authors chose to make it do so.
GCC in particular allows, by default, a lot of non-standard stuff that was historically accepted by old C compilers. They like "compatibility" in that sense.
What does the standard say about [it]?
Precisely what the warning states it says about it: ISO C++ forbids variable length arrays.
C++ does not have VLAs.
Where you see one being accepted, it is a compiler extension; to find out how that compiler implements such an extension, you would have to ask the compiler's authors (or examine its source, if applicable).
The standard requires that a conforming compiler must "issue a diagnostic" when it encounters something that is illegal. Having done that, it's free to continue to compile the code with an implementation-specific meaning. (Note that "with an implementation-specific meaning" is a polite form of "with undefined behavior").
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);
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];