can use " int a = {0} " in C programe to init a array? - c

I found this code , when I compile it ,
the compiler tell me "subscripted value is neither array nor pointer" .
I know my platform is old .
but I want know that "unsigned int bValue = {0}" is a new way to init array ?
unsigned int bValue = {0};
uBlockSize = sizeof(bValue) / sizeof(unsigned int);
for (i = 0; i < uBlockSize; i++)
bValue[i] = ui8Value << 24U |
ui8Value << 16U |
ui8Value << 8U |
ui8Value;
I want know that "unsigned int bValue = {0}" is a new way to init array ?

You declared a scalar object of the type unsigned int
unsigned int bValue = {0};
That is it is not an array declaration and hence you may not use the subscript operator with the identifier bValue. And the compiler reports about this prohibition.
However you may initialize scalar objects with expressions optionally enclosed in braces.
From the C Standard (6.7.9 Initialization)
11 The initializer for a scalar shall be a single expression,
optionally enclosed in braces. The initial value of the object is
that of the expression (after conversion); the same type constraints
and conversions as for simple assignment apply, taking the type of the
scalar to be the unqualified version of its declared type.
That is the declaration itself is correct. Only it declares not an array but a scalar object.
You could declare an array for example the following way
unsigned int bValue[] = {0};
In this case bValue is an array with one element initialized by 0.

The code doesn't compile (I tested the latest versions of clang, gcc and MSVC) because bValue[i] is not applicable to a scalar. bValue doesn't appear to be an array (maybe the original code looks different?); therefore, any attempt at indexing will result in compilation error.
As correctly pointed out by #nielsen, the initialization in itself is correct, although it's more often seen applied to arrays.

Related

why am i getting warnings errors due to assignment of a variable's address to a pointer in the global scope?

this the snip of the warning i was getting when i tried to compile the program.I am just getting started with pointers and this following program is being flagged by compiler for some reason I am not able comprehend. the code is as follows:
#include <stdio.h>
int dec = 0;
int *d;
d = &dec;
int main() {
return 0;
}
there is no error when I am stuffing these declarations in to main's body. the version of gcc I am using is gcc version 12.2.0(downloaded using MSYS2) and code editor MS visual code.can anybody post an explanation for this?
as i have stated above i have randomly started typing a program to get familiar with pointers, i expected there to be no variation in the treatment of pointers regardless of where they are being declared and intialised.
You're attempting to perform an assignment outside of a function, which is not allowed. What you can do is initialize:
int *d = &dec;
You may use only declarations in file scopes.
In the provided program you are using an assignment statement
d = &dec;
in the file scope. So the compiler issues an error.
Instead you could write for example
#include <stdio.h>
int dec = 0;
int *d = &dec;
int main( void ) {
return 0;
}
As the variable dec has static storage duration then the expression &dec is an address constant and my be used as an initializer for the variable d that also has static storage duration.
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
and (6.6 Constant expressions)
7 More latitude is permitted for constant expressions in initializers.
Such a constant expression shall be, or evaluate to, one of the
following:
— an arithmetic constant expression,
— a null pointer constant,
— an address constant, or
— an address constant for a complete object type plus or minus an
integer constant expression.
and
9 An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary
& operator or an integer constant cast to pointer type, or
implicitly by the use of an expression of array or function type. The
array-subscript [] and member-access . and -> operators, the address &
and indirection * unary operators, and pointer casts may be used in
the creation of an address constant, but the value of an object shall
not be accessed by use of these operators.

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.

can't I use double in array?

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] );

C Pre-Processor Macro code with () and {}

#include <stdio.h>
#define a (1,2,3)
#define b {1,2,3}
int main()
{
unsigned int c = a;
unsigned int d = b;
printf("%d\n",c);
printf("%d\n",d);
return 0;
}
Above C code will print output as 3 and 1.
But how are #define a (1,2,3) and #define b {1,2,3} taking a=3 and b=1 without build warning, and also how () and {} are giving different values?
Remember, pre-processor just replaces macros. So in your case you code will be converted to this:
#include <stdio.h>
int main()
{
unsigned int c = (1,2,3);
unsigned int d = {1,2,3};
printf("%d\n",c);
printf("%d\n",d);
return 0;
}
In first case, you get result from , operator, so c will be equal to 3. But in 2nd case you get first member of initializer list for d, so you will get 1 as result.
2nd lines creates error if you compile code as c++. But it seems that you can compile this code in c.
In addition to other answers,
unsigned int d = {1,2,3};
(after macro substitution)
is not valid in C. It violates 6.7.9 Initialization:
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
With stricter compilation options (gcc -std=c17 -Wall -Wextra -pedantic test.c), gcc produces:
warning: excess elements in scalar initializer
unsigned int d = {1,2,3};
^
However, note that
unsigned int d = {1};
is valid because initializing scalar with braces is allowed. Just the extra initializer values that's the problem with the former snippet.
For c, the initializer is an expression, and its value is 3. For d, the initializer is a list in braces, and it provides too many values, of which only the first is used.
After macro expansion, the definitions of c and d are:
unsigned int c = (1,2,3);
unsigned int d = {1,2,3};
In the C grammar, the initializer that appears after unsigned int c = or unsigned int d = may be either an assignment-expression or { initializer-list } (and may have a final comma in that list). (This comes from C 2018 6.7.9 1.)
In the first line, (1,2,3) is an assignment-expression. In particular, it is a primary-expression of the form ( expression ). In that, the expression uses the comma operator; it has the form expression , assignment-expression. I will omit the continued expansion of the grammar. Suffice it to say that 1,2,3 is an expression built with comma operators, and the value of the comma operator is simply its right-hand operand. So the value of 1,2 is 2, and the value of 1,2,3 is 3. And the value of the parentheses expression is the value of the expression inside it, so the value of (1,2,3) is 3. Therefore, c is initialized to 3.
In contrast, in the second line, {1,2,3} is { initializer-list }. According to the text in C clause 6.7.9, the initializer-list provides values used to initialize the object being defined. The { … } form is provided to initialize arrays and structures, but it can be used to initialize scalar objects too. If we wrote unsigned int d = {1};, this would initialize d to 1.
However, 6.7.9 2 is a constraint that says “No initializer shall attempt to provide a value for an object not contained within the entity being initialized.” This means you may not provide more initial values than there are things to be initialized. Therefore, unsigned int d = {1,2,3}; violates the constraint. A compiler is required to produce a diagnostic message. Additionally, your compiler seems to have gone on and used only the first value in the list to initialize d. The others were superfluous and were ignored.
(Additionally, 6.7.9 11 says “The initializer for a scalar shall be a single expression, optionally enclosed in braces.”)

Initializer element is not constant in C [duplicate]

This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
I'm coming from javascript/php/python and probably I'm missing something, here is the code:
const int a = 50;
const int c = 100;
const int d = 100;
int endX = c + a;
int endY = d;
int startX, startY, b;
I get
ex1.4.c:6: error: initializer element is not constant
ex1.4.c:7: error: initializer element is not constant
Does someone have an explanation?
Unfortunately, in C const variables are not really const.
Below are the extracts from the c99 standard.
6.7.8 Initialization
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string
literals.
The constants are defined as follows:
6.4.4 Constants
Syntax
constant:
integer-constant (e.g. 4, 42L)
floating-constant (e.g. 0.345, .7)
enumeration-constant (stuff in enums)
character-constant (e.g. 'c', '\0')
The standard defines constant expressions as follows:
6.6 Constant expressions
(7) More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one
of the following:
— an arithmetic constant expression,
— a null pointer constant,
— an address constant, or
— an address constant for an object type plus or minus an integer constant expression.
(8) An arithmetic constant expression shall have an arithmetic type and shall
only have operands that are integer constants, floating constants,
enumeration constants, character constants, and sizeof expressions.
Cast operators in an arithmetic constant expression shall only convert
arithmetic types to arithmetic types, except as part of an operand to
a sizeof operator whose result is an integer constant.
Thus, c and a are not constant expressions and cannot be used as initializers in your case.
const expressions must be a compile time constant in C unlike in C++ therefore c+a can't be used as a constant. The usual way to handle this problem in C is to use the preprocessor instead:
#define A 50
#define C 100
#define D 100
int endX = C + A;
int endY = D;
int startX, startY, b;
If you are declaring endX as a global variable the error makes sense.
The reason is that global variables are initialized in compiling time, and you are trying to initialize endX as an operation that must be done in execution time.
Yeah, you can't initialize something to a variable. The compiler does the initialization and at compile time it doesn't know the value of c+a;
The int x = 1; type initialization is fine, the compiler just puts a 1 at the address of x in the object code.
To initialize something to c+a, you want to do it at runtime, in the startup code in c or constructor in C++.
In C programming langages, objects with static storage duration must be initialized with constant expressions (or aggregate containing constant expressions). If endX has static storage duration, its initializer (c+a) is not a constant expression (i.e. the expression cannot be evaluated during translation phase).

Resources