why can't I initialize the array like this? [duplicate] - c

This question already has answers here:
Initializing variable length array [duplicate]
(3 answers)
Variable-length arrays in C89?
(3 answers)
Closed 8 years ago.
#include<stdio.h>
main() {
int a=5;
int array[a]={0};
printf("Success\n");
}
when i am executing the program it will through a error as
b.c: In function ‘main’:
b.c:8:1: error: variable-sized object may not be initialized
b.c:8:1: warning: excess elements in array initializer [enabled by default]
b.c:8:1: warning: (near initialization for ‘array’) [enabled by default]
In cc complier . but i can assign like this
int array[5]={0};
If anyone correct me?

This statement
int array[a]={0};
declares a Variable Length Array (VLA).
According to C Standard (6.7.9 Initialization)
3 The type of the entity to be initialized shall be an array of
unknown size or a complete object type that is not a variable length
array type.
The problem is that the compiler shall know the array size at compile time that to generate the code that initialize an array.
Consider an example
void f( size_t n )
{
int a[n] = { 1, 2, 3, 4, 5 };
//...
}
Here is a is a variable length array. Now as n can have any value then the number of initializers in the array definition can be greater than the size of the array. So this code breaks the Standard from another side because the number of initializers may not be greater than the number of elements of array. On the other hand if the number of initializers less than the number of elements of array then what to do in this case? Maybe the programmer did not mean that some elements shall be zero-initialized.
As for this declaration
int array[5]={0};
then there is no variable length array. The size of the array is known at compile time. So there is no problem
.

"Variable-length automatic arrays are allowed in ISO C99, and as an
extension GCC accepts them in C90 mode and in C++"
says here.
Compilers can differ in some situations. It's normal to have problems with variable-sized arrays. This should work if you really need to do this
#include<stdio.h>
#DEFINE A 5
main()
{
int array[A]={0};
printf("Success\n");
}

The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.

Related

why does it show compiler error if i initialize the array whose size is not specified?

Why does this show compiler error if i don`t specify the size of the array before and try to initialize it?
int main()
{
int ar[] = {};
int n = 5 ;
for(int i = 0; i < n ; i++)
ar[i] = i+1;
}
From C11, chapter 6.7.6.2,
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation
So, this syntax
int ar[] = {};
is a constraint violation. If you enable basic compiler warning, you should see something like
In function ‘main’:
error: ISO C forbids empty initializer braces [-Werror=pedantic]
int ar[] = {};
^
error: zero or negative size array ‘ar’
int ar[] = {};
To answer why there is a compiler error, maybe it's useful to think about the structure of the memory used by the program.
When the program is executing the function referenced in the question it adds a frame to the stack.
"Adding a frame" just means the information for the current function is added onto the end of the stack and when the program runs the code it needs to also create space for the array.
To me the given syntax could only mean a dynamically sized array, meaning items could be added or removed arbitrarily resizing the structure.
The problem with this is that arrays are stored on the stack and since there's usually things added after the function variables in the frame of a function there's no space to add more items to the array!
Therefore it seems like C would create many issues by allowing this use and specifying a size for your array allows the program to use that amount of space in the stack which causes no memory issues with the stack during runtime.
You are declaring and initializing a zero-length array (GNU C extension) in that line:
int ar[] = {};
The uses of zero-length arrays are rare (e.g. tail padding structs, for alignment purposes), and your code does not look like it's meant to be using it, so you are probably doing so by accident.

Does this code have a valid declaration for the size of the array? [duplicate]

This question already has an answer here:
Declaring an array with a non-constant size variable [duplicate]
(1 answer)
Closed 5 years ago.
I am learning how to program arrays in C. I have a question about the following code regarding size of array. In the below code, is it a valid declaration of size of an array? Please explain me if it is either valid or invalid.
#include<stdio.h>
#define SIZE 10
int main(void) {
int size=12;
float salary[size];
salary[0]=890.54;
printf("%f",salary[0]);
return 0;
}
To support the other answer, if variable length arrays (VLA) are supported then yes — the declaration in the question is valid and defines a VLA. VLAs made their debut in C99 and then in C11 they are made optional. A conforming C11 compiler that does not support VLAs defines __STDC_NO_VLA__.
From §6.7.6.2¶4
If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)
from §6.10.8.3¶1
__STDC_NO_VLA__
The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types
It's valid size value (only with C99). You can refer from this URL for more detail:
https://www.cs.uic.edu/~jbell/CourseNotes/C_Programming/Arrays.html

Precedence of assignment [duplicate]

This question already has answers here:
int q = {1,2}; peculiar initialization list
(1 answer)
"int *nums = {5, 2, 1, 4}" causes a segmentation fault
(5 answers)
Closed 5 years ago.
In c ,
main() {
int a = (1,2,3,4);
printf("%d",a);
}
yields an output of
4
This is because comma(,)operator has a right to left precedence .
But
main() {
int a = {1,2,3,4};
printf("%d",a);
}
yields an output
1
anyone pls explain the logic behind this.
Thanks
{1,2,3,4} is the syntax for an initializer, used to initialize something that has more than one value, like an array or a struct. So the commas inside it are not operators, they are just part of the initializer syntax.
When initializing, C uses the values from the initializer from the left. As you initialize a single scalar variable, only one element is needed.
Your compiler is supposed to tell you that this code doesn't make sense:
x.c:2:12: warning: excess elements in scalar initializer
int a = {1,2,3,4};
^
I should add that this code violates a constraint of the standard, see C11 draft N1570, § 6.7.9 -- 2:
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
This requires the compiler to emit a diagnostic when compiling such broken code.
From the same paragraph is the following rule (number 17):
Each brace-enclosed initializer list has an associated current object. When no
designations are present, subobjects of the current object are initialized in order according
to the type of the current object: array elements in increasing subscript order, structure
members in declaration order, and the first named member of a union.1
So your compiler decides to do the "next closest" thing to the standard and just use the first value you provide.
That's an initializer (usually used for arrays), but you are not using it wisely, didn't your compiler tell you?
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
main.c:2:13: warning: excess elements in scalar initializer
int a = {1,2,3,4};
^
The precedence here is from left to right, and since you have only one element to initialize, one element is chosen from the initializer (that is 1 in this case).
The curly braces mean initialization of the variable, mostly useful for arrays.
In your case, compiling with gcc yields:
test.c:6:12: warning: excess elements in scalar initializer
int a = {1,2,3,4};
^
(same for 3 & 4)
Means that only value 1 is useful for your case (it's a scalar)

sizeof array without explicit length

Can sizeof safely be used on an array that has been declared without an explicit size specified inside the square brackets, but which gets initialised in the declaration?
Consider the following code:
unsigned int arr[] = { 1, 2, 3 };
size_t bytes = sizeof arr;
If compiled on macOS with clang-800.0.42.1 without any special compiler flags, this yields the expected result of 12.
But does the C standard (or any C standard, if they differ on this) guarantee this to be the case? Or do I have to declare it like unsigned int arr[3] in order for it to be "sane"?
Yes, the standard guarantees that the array element count will be equal to the number of elements in the array initializer in case no size is specified. See
C11 standard draft 6.7.9p22 and 6.7.9p25:
If an array of unknown size is initialized, its size is determined by
the largest indexed element with an explicit initializer. The array
type is completed at the end of its initializer list.
EXAMPLE 2 The declaration
int x[] = { 1, 3, 5 };
defines and initializes x as a one-dimensional array object that has three elements, as no size was specified and there are three initializers.
unsigned int arr[] = { 1, 2, 3 }; actually defines a complete array. The size of the array is known in this compilation unit and is n*sizeof(type) where n is the number of elements in the initialization list (here 3) and type is the underlying object type (here unsigned int).
That means that sizeof(arr) is defined in same scope as arr and has the expected value.
What would be completely different would be extern int arr[];. That would be a simple declaration that an array of that name will be provided in another compilation unit, but the compiler has no way to know its size. In that case using sizeof(arr) will be an error.
Another example of mere declaration is
void func(int arr[]) {
...
}
Here again the compiler only knows that the function will receive an int array, but again cannot know its size. But here the compiler generates a pointer that will receive the address of the array and sizeof(arr) is defined but is the size of that pointer and not the size of the original array.

gcc error generation

Why does neither gcc or clang generate an error when I try to compile code containing the following two lines?
int palindrome(char s[]){
char s2[strlen(s)];
I thought in such an instance you would have to dynamically allocate memory to s2.
GCC has an extension for this behavior, and it's also standard in C99, known as variable length arrays.
http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
Clang supports it due to GCC C and C99: http://clang.llvm.org/compatibility.html#vla
Section 6.7.5.2 Array declarators:
If the size is not present, the array type is an incomplete type. If
the size is * instead of
being an expression, the array type is a variable length array type
of unspecified size,
which can only be used in declarations with function prototype
scope) such arrays are
nonetheless complete types. If the size is an integer constant expression
and the element
type has a known constant size, the array type is not a variable
length array type;
otherwise, the array type is a variable length array type.
And an example from 6.5.3.4:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf (not the standard, but a draft, and free. :)

Resources