Following piece of code compiles in gcc. But it is not correct way of writing as it surpasses the use of malloc function. What is the problem in this code?
#include<stdio.h>
main()
{
int n;
scanf("%d",&n);
int a[n];
}
your code is legal ISO C99 code. It's not C89 ANSI compliant: if you are stuck with compatibility rules, because of old compilers or company policies, you need to use malloc().
More importantly, in C99, using your definition, the array is allocated on stack, that is usually a limited resource, while with malloc() it's allocated in the heap.
Your array is a variable length array (VLA). This is an advanced feature of C, introduced in the C99 version of the standard.
The problem with VLAs is that they can easily overflow the stack. Unless you have a specific reason to use a VLA, use dynamic memory with malloc and avoid the risk of stack overflow.
Your main declaration is wrong. It should be
int main(void)
"...it is not correct way of writing as it surpasses the use of malloc function..." - what is that supposed to mean? According to the rules of modern C language, the only problem with your code is the missing int in the declaration of main. I.e. it has nothing to do with any malloc.
It can be said that your code is self-contradictory in a sense that it uses a perfectly valid C99 feature - variable length array int a[n] - but at the same time relies on an obsolete feature of C89/90 - implied int in the declaration of main, which is no longer supported by C99.
You need to decide which version of C language you are trying to use - C89/90 or C99. Once you make that decision, we'll be able to discuss the correctness of your code.
Related
I have this code below which creates an array of variable size that compiles and runs fine on my mac.
#include <stdio.h>
#include <stdlib.h>
int main(){
int w = 100;
int ar[w];
ar[2] = 42;
printf("%d\n",ar[2]);
}
I thought variable sized arrays were not permitted in C. what is happening here exactly? How is memory being managed? Does the memory get dynamically allocated at run time? Thanks
What's happening here is that variable-length arrays are a relatively new feature, only first appearing in the C standard in 1999. C standards are not adopted as quickly in the C world as JavaScript and Python; I can remember the excitement in 2007 or so when my workflow was finally able to include VLAs.
To add insult to injury, while C++ is a mostly-superset of C, VLAs are not supported, meaning that the common use-case of folks compiling C code with C++ compilers will not work.
There was enough pushback from the compiler vendors that the standard eventually (C11) made VLAs optional, mandating the feature-test macro __STDC_NO_VLA__ instead.
(see ISO stadndard 9899:2011 Programming Languages - C, section 6.7.6.2 4)
This code:
int main() {
int size;
scanf("%d", &size);
int array[size];
}
works fine with GCC, but VC expects a constant expression for the size of the array so does not compile it (which makes more sense to me). Any idea why it works with GCC?
Yes, because gcc supports variable length arrays.
It was added as a part of C99 standard, however, in the later standards (C11 and C18), it's an optional feature.
Because variable-length arrays (VLAs) are neither valid in C90 nor C++11 MSVC does not support them:
From https://learn.microsoft.com/en-us/cpp/build/reference/za-ze-disable-language-extensions?view=vs-2019:(
The C compiler is an C89/C90 compiler that, by default, enables
Microsoft extensions to the C language.
VLAs may be best avoided in any event because a C11 compiler need not implement them and they are potentially unsafe. Typically an implementation will allocate VLAs on the stack. In your code, it only takes a user to enter an arbitrarily large value to break your code in someone-deterministic manner - any use of VLAs should have some constraint test to ensure the length is reasonable and in the capability of the system to support.
i am solving a problem. In my code i have two arrays
array[];
array2[];
i am inputing 2 numbers through scanf , and i want the size of arrays to be the count of number 1 and 2 e.g
int x;
int y;
scanf(" %d %d\n",&x,&y);
int indexX[x*y];
int indexY[x*y];
This does not work.
Being new to C im quite lost how to implement it , is the only way dynamicly allocate memory? If no , how can i achieve wanted result ? Or how could i dynamicly alocate the memory for it?
my code throws error
warning: ISO C++ forbids variable length array ‘indexX’ [-Wvla]
warning: ISO C++ forbids variable length array ‘indexY’ [-Wvla]
According to your error messages, you compile with a C++ compiler. Do not! C is not C++ and C++ is not C with classes. They are different languages. As the messages state, C++ does not provide VLAs (see below).
Use a standard-compliant C compiler, or at least a C99 compiler. Variable length arrays (VLAs) were added with the C99 release of the standard as a mandatory feature. C11 relaxed this by making it optional, but most (if not all) compilers which support C99 also implement it in C11 mode.
before defining the array, you should verify scanf really set these two variables by checking the result of scanf. Otherwise you use uninitialised variables, which is undefined behaviour and may (likely - will) result in strange behaviour - at best.
Additinally you can also initialise the variables before scanf to 1 (a VLA of size 0 is also undefined behaviour). This way you can check later and are still safe with the VLA definition.
Warning: Most, if not all modern implementations place VLAs on the stack. The size of the stack is normally limited to some 100 bytes (embedded systems) up to some MiB (standard OS like Windows, OS-X, Linux). There is no check if the VLA fits onto the stack, so you should not allocate too large arrays. If you are not sure, better use dynamically allocated memory (malloc& friends).
So for example,
int aaa(unsigned int par1, unsigned int par2){
int array[par1*par2];
return 0;
}
I tried compiling the code that contains this, and it compiled well and had no run-time issue - the array was properly created.
But I know that this is basically declaring a dynamic array in static array declaration fashion. What may go wrong with this declaration? Will there be a compiler issue in a different compiler?
This is correct as per the 1999 C standard. The 2011 standard changed it to be an optional feature, which in practice means that all C11 compilers will support it except for MSVC.
Before 1999 some compilers offered this as a non-standard extension.
Here is a link to StackOverflow search for other questions on this topic.
But I know that this is basically declaring a dynamic array in static array declaration fashion.
This is called VLA (Variable-Length Array). This array is not static - it is placed in automatic memory (also known as "the stack").
What may go wrong with this declaration?
It may overflow the stack when the size of the array exceeds a certain limit specific to your system.
Will there be a compiler issue in a different compiler?
This is a C99 feature, so compiler that do not support C99 may fail to compile this code.
I believe this is a C99-only feature. It's called VLA (variable-length arrays).
The C++0x does't support VLA:
https://groups.google.com/forum/#!topic/comp.std.c++/K_4lgA1JYeg
But some compilers might not be strictly compliant with the standard.
I know that I'm not supposed to do this in C90, and it's a rather basic stuff.
char name[strlen(s)];
ArrayLength.c:11: warning: ISO C90 forbids variable length array ‘name’
Did they want me to specifically use malloc? I'm just curios here about the logic behind it.
It's forbidden because C90 doesn't support variable-length arrays (VLAs). It's really as simple as that.
Your options are:
Declare a fixed-length array that can cope with the maximum string length you want to work with.
Dynamically-allocate the array (using malloc).
Work with a compiler that offers VLAs a non-standard language extension, e.g. GCC. (I don't recommend this, because it means you'll end up writing non-portable code.)
Use C99 instead, where VLAs are supported. Note that VLAs are allocated on the stack, which can cause all sorts of issues if you run out of stack space (unlike with malloc, there's no concept of being able to check that the allocation was successful).
[Note: If you're allocating an array in order to make a copy of s, you'll need to use strlen(s)+1 as the size (remember the null terminator).]
It's not that "they" don't want you to do it, it's simply not part of the language (or rather, wasn't prior to 1999). The standard workaround is to use malloc or alloca. (alloca is essentially identical to variable length array allocation, but is not a standard function, so it may not be available on all systems of interest. Also, some people have strong objections to it's use, but they tend to object strong to variable-length arrays for the same reasons.)
This warning points to the usage of a GNU gcc extension is a serious portablity problem.
The code is illegal, because the value of strlen(s) is not known at compile time. GNU gcc provides an extension for automatic arrays that allocate based on run time values; but relying on these makes the code out of compliance with the standard.
If the value of strlen(s) isn't known until run-time then one can bring the code into compliance by either converting to performing the allocation/deallocation explicitly on conventions arrays, or by using STL containers.(e.g. std::vector).
It's a matter of the language having restrictions for the presumed convenience of the
compiler and its intended runtime environment.