can't I use double in array? - c

what's problem here?
it shows a bug, help me I'm a beginner.
can I use double in array?
#include <stdio.h>
int main()
{
double a;
scanf("%lf",&a);
double s[a];
double b,c=0, d;
for(b=0;b<a;b++){
scanf("%lf",&s[b]);
}
for(b=0;b<a;b++){
c = c + s[b];
d=b+1;
printf("%lf\n",c/d);
}
return 0;
}

In case it isn't clear, your array cannot be of double length. It's undefined behavior.
This is because a double is not an integer, but a rational number that could be an integer. A simple way to understand this issue is to take some floating point value, say 3.5.
What is an array of length 3.5 Is it 3 and a half slots of some size in contiguous memory? Is is enough slots for 3? 4? 3.5 slots would likely be useless and unintended, and if it's not a fractional slot, it might be unclear and likely unintended, hence undefined behaviour.
While the other people have proposed solutions creating an integral type, you cannot create an array of double length. You can create an array of doubles, ie
double arr[5];
But you can't create an array of double length like
int arr[3.3];

Use this :
int a;
scanf("%d",&a);
Rest of your code is just fine .

While variable length arrays are supported in modern C, the size of an array must be positive and integral.
What you could do instead is round to the nearest size_t:
size_t ASIZE = ceil(fabs(a));
double s[ASIZE];
Include <math.h> to access ceil and fabs.

You cannot use floating-point types (float or double) to specify an array size or array index:
6.7.6.2 Array declarators
Constraints
1 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.
C 2011 Online Draft
6.5.2.1 Array subscripting
Constraints
1 One of the expressions shall have type ‘‘pointer to complete object type’’, the other
expression shall have integer type, and the result has type ‘‘type’’.
ibid.
So a and b must be of integral type - I typically use size_t for array size and index variables:
size_t a;
printf( "Gimme the array size: " );
scanf( "%zu", &a );
double s[a];
for ( size_t b = 0; b < a; b++ )
scanf( "%lf", &s[b] );

Related

Returning a pointer to array of unknown size and promoting it to the desired length

I have a function that takes two 2d matrices of variable dimensions and returns a matrix of equal dimensions.
double (*sumOfMatrices(size_t rows, size_t columns, double matrixA[][columns], double matrixB[][columns]))[] {
double (*result)[columns]= malloc(rows * sizeof *result);
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < columns; j++)
{
result[i][j]= matrixA[i][j] + matrixB[i][j];
}
}
return result;
}
Then I declare a variable like this
double (*sumResult)[n]= sumOfMatrices(m, n, matrixA, matrixB);
Is this undefined behavior? The compiler doesn't say anything, yet I feel that initializing a double(*)[n] with a double(*)[] is implicitly promoting the data type. Is there a way that I can return double(*)[columns] instead?
This code is valid.
The return type of the function is double (*)[], i.e. a pointer to an array of unspecified size of type double. The return statement in this function is converting a double (*)[columns] to that type, and the assignment of the return value in the calling function performs the opposite conversion.
Two pointer types are compatible if they point to compatible types. So now we compare the types double [columns] and double []. Two arrays are compatible if the element types are compatible and, if both specify a size, that the sizes are the same. Since only one specifies a size, the array types are compatible, and therefore so are the pointers to the arrays.
Sections 6.7.6.1p2 and 6.7.6.2p6 of the C standard spell out this compatibility in more detail:
6.7.6.1p2
For two pointer types to be compatible, both shall be identically qualified and both shall
be pointers to compatible types.
6.7.6.2p6
For two array types to be compatible, both shall have compatible element types, and if
both size specifiers are present, and are integer constant expressions, then both size
specifiers shall have the same constant value. If the two array types are used in a context
which requires them to be compatible, it is undefined behavior if the two size specifiers
evaluate to unequal values.
So let's say n is 5. The function then creates a pointer to an array whose type is double (*)[5]. This type is converted to double (*)[] when it is returned from the function, then converted back to double (*)[5] when assigned to sumResult whose type matches the original type.
So both conversions are valid, and use of sumResult is valid.

Why this 'sizeof()' return is 0 bytes in C? [duplicate]

This question already has answers here:
How can this structure have sizeof == 0?
(4 answers)
Closed 1 year ago.
my question is about sizeof and Memory Allocation. When I was studying C and testing type values I tried this code:
#include <stdio.h>
int main(void) {
char vec[0];
vec[0] = 1;
printf("\n SIZEOF: %li", sizeof(vec));
printf("\n VEC[0]: %li", vec[0]);
}
The output was:
> SIZEOF: 0
> VEC[0]: 1
Why "vec[0]" has a size of "0 bytes" even I adding value "vec[0] = 1" ? (If I don't add this value, just declare the vector "char vec[0] or int vec[0]" the output is same).
Ricxk. ty for your time.
This code snippet
char vec[0];
vec[0] = 1;
invokes undefined behavior.
You may not declare an array with zero elements.
From the C Standard (6.7.6.2 Array declarators)
1 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.
Pay attention to that there are used incorrect conversion specifiers in these calls of printf
printf("\n SIZEOF: %li", sizeof(vec));
printf("\n VEC[0]: %li", vec[0]);
For a value returned by the operator sizeof that has the type size_t you should use the conversion specifier %zu and for an object of the type char you should use the conversion specifier %c.
As for your question
Why "vec[0]" has a size of "0 bytes" even I adding value "vec[0] = 1"
? (If I don't add this value, just declare the vector "char vec[0] or
int vec[0]" the output is same).
then the compiler should issue a message relative to the invalid declaration of an array.
As for the output then as the array is not a variable length array then the value of the expression sizeof( vec ) is evaluated at compile time. The compiler sees that the number of elements is equal to 0 and it calculates the expression sizeof( vec ) as 0 * sizeof( char ). Thus this expression always yields 0 independent on the array element type.
vec is defined as being an array which is zero elements in size. The size of zero elements is zero, which seems to be sensible. Assigning a value to vec[0] is overwriting memory somewhere.
Arrays must be defined with a positive size.
You created one with 0 size which is a constraint violation, so your code exhibits undefined behavior.
You are not actually filling a position in the "array" of length 0 vec when you write vec[0] = 1;.
Remember, when you declare an array of length N, its valid indices are 0, 1, 2 ... N-1. What are the valid indices if an array has size 0? None of them!
This is the same sort of undefined behavior as:
int data[3] = { 1, 2, 3 };
data[10000] = 10;
It may work on your system to write to vec[0], but it's still not memory that belongs to the vec.

Can array length in declaration be non-constant?

I am a bit confused about array declaration in C. I know that it's possible to do this:
int a[20]; // Reserved space for 20 int array
int b[] = {32, 431, 10, 42}; // Length in square brackets is auto-calculated
int *c = calloc(15, sizeof(int)); // Created a pointer to the dynamic int array
But is it possible to do this?:
int my_array[sizeof(int) * 5];
Is it a valid code, or an array length should be a constant expression (in ANSI C)?
This declaration
int my_array[sizeof(int) * 5];
does not declare a variable length array because the expression sizeof(int) * 5 is a constant integer expression. So even your compiler does not support variable length arrays you may use such a declaration.
From the C Standard (6.6 Constant expressions)
6 An integer constant expression117) shall have integer type and shall
only have operands that are integer constants, enumeration constants,
character constants, sizeof expressions whose results are integer
constants, and floating constants that are the immediate operands of
casts. Cast operators in an integer constant expression shall only
convert arithmetic types to integer types, except as part of an
operand to the sizeof operator.
and (6.7.6.2 Array declarators)
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; 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.)
A declaration of a variable length array can look like
const int n = 5;
int my_array[sizeof(int) * n];
The support of variable length arrays is optional in C11 and higher.
(This answer answers the question in the title, “Can array length in declaration be non-constant?” The example given in the body, int my_array[sizeof(int) * 5]; does not have a non-constant length.)
Variable length arrays are optional in the current C standard, 2018, meaning a C implementation may choose to support them or not. They were mandatory in the 1999 C standard and made optional in the 2011 standard.
Variable length arrays can be declared only inside functions or there parameters, not at file scope, and they cannot have static or thread storage duration.
sizeof(int) * 5 used in the example statement in your question: int my_array[sizeof(int) * 5];, is a constant expression, so although it does not serve as a good illustration of your primary question, it is legal syntax for C array declaration.
With the exception of C99, variable length arrays are optional in most recent C compiler implementations. (In C99 inclusion of VLA is mandated.)
So, if your compiler supports VLA, the following are an examples:
char string[100] = {0};
scanf("%99s", string);
int VLAarray1[strlen(string)+1];//per question in comments about functions to size array.
memset(VLA1array, 0, sizeof(VLAarray1));//see Note below for initialization
int arrayLen = 0;
scanf("%d", &arrayLen);
int VLAarray2[arrayLen];
memset(VLAarray2, 0, sizeof(VLAarray2));//see Note below for initialization
int nonVLAarray[100] = {0};//initialization during declaration of nonVLA
Note: that VLAs cannot be initialized in any form during its declaration. As with all variables though it is a good idea that it be initialized in subsequent statements by explicitly assigning values to its entire region of memory.
Passing VLAs as function arguments is not included within the scope of your question, but should it be of interest, there is a good discussion on that topic here.

runtime const value set for arr size and no error

#include <stdio.h>
int func()
{
int a = 3, b = 4;
int c = a * b;
return c;
}
int main()
{
const int N = 10;
int arr[N];
printf("size = %ld\n", sizeof(arr));
int x = 10;
const int SIZE = x;
int buf[SIZE];
printf("size = %ld\n", sizeof(buf));
const int FN = func();
int buf2[FN];
printf("size = %ld\n", sizeof(buf2));
return 0;
}
ubuntu 20 5.4.0-42-generic
gcc 9.3.0
compile:
gcc const_create_arr.c -Wall
show no warning
output:
size = 40
size = 40
size = 48
output corret
the last one FN is init by func(). we know that func() return vlaue should be computed in runtime. But an array definition should provide the true length of this array to compiler to help compiler allocate space. So I think the last one should not be passed at compiling. But it seems corret. I want to know how it works. Whether my gcc has optimise it and compute the func return when it compiling.
In all three cases you're creating a variable length array. For an array to not be a VLA the size needs to be an integer constant expression, and a variable with the const qualifier (no matter how it's initialized) does not qualify as one.
The definition of a VLA can be found in section 6.7.6.2p4 of the C standard regarding 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 or type names 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 the definition of an integer constant expression is given in section 6.6p6:
An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.
There is nothing in this definition that qualifies a const qualified variable as an integer constant expression, so the sizeof operator in each of the three cases is being evaluated at runtime because the arrays are VLAs.
C has variable length arrays, so int x[y] is valid C provided y is defined in advance. It doesn't matter if y is const or not, it just needs to be > 0 to make any sense, as well as small enough that you don't use up the entire stack.
In this case y is 12, so you get a length 48 (12 * sizeof(int) where that's 4). This gets computed after the fact, not in advance like you might expect for something trivial like sizeof(int).
In C++ this is not the case as defined by the standard, however some compilers will still do it the C way.

Pointer operation yields unexpected result

I was expecting the code below to print 4 (since a float is 4 bytes), but it prints 1. Would someone explain why this happens?
#include <stdio.h>
int main()
{
float a[4]={0.0,0.1,0.2,0.3};
printf("%d", &a[1]-&a[0]);
return 0;
}
First of all, change
printf("%d", &a[1]-&a[0]);
to
printf("%td", &a[1]-&a[0]);
as the result type of two subtraction yields a type ptrdiff_t and %td is the conversion specifier for that type.
That said, quoting C11, chapter §6.5.6, subtraction operator (emphasis mine)
When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements. [....] In
other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of
an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t. [....]
In your case, P is &a[1] and Q is &a[0], so i is 1 and j is 0. Hence the result of the subtraction operation is i-j, i.e., 1-0, 1.
You are correct that the two pointers are 4 bytes apart. And if you were subtracting two integers you'd get 4. But &a[1] and &a[0] are of type float *. Pointer arithmetic in C takes into account the size of the thing being pointed to, so &a[1]-&a[0] is 1.
This is the basic means by which array indexing works. You can take advantage of this to iterate through an array without needing a separate index and instead terminating on a boundary such as NaN.
#include <stdio.h>
#include <math.h>
int main()
{
float a[] = { 0.0,0.1,0.2,0.3,NAN };
float *iter = a;
while(!isnan(*iter)) {
printf("%f\n", *iter);
iter++;
}
}
If you instead cast the values to unsigned int you will indeed get 4.
printf("%u\n", (unsigned int)&a[1]-(unsigned int)&a[0]);

Resources