Error while allocating memory to a structure pointer [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to allocate memory for my structure pointer which I am declaring globally. But I am getting this error --> error: initializer element is not constant
typedef struct A {
uint32_t arr[30][4096];
uint32_t var1;
uint8_t var2;
bool var3;
}B;
B *x = (B*)malloc(sizeof(B));
Can anyone explain me where I am doing it wrong.
Also, instead than dynamic memory allocation, is there a direct way to allocate memory to structure pointers?
Thanks in advance.

You cannot use malloc in global scope like declaring a variable.
You must use constant to init a variable in global scope.
You can use it (it is a function call) inside a function
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint32_t arr[30][4096];
uint32_t var1;
uint8_t var2;
bool var3;
}A;
A *x;
int main()
{
x = malloc(sizeof(A));
if (x != NULL)
{
free(x);
}
return 0;
}
Form 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.

C doesn't allow you to have generic statements or expressions in the global scope (outside of functions), not even for initializers. Only compile-time constants are allowed as initializers in the global scope.
If you want to initialize the pointer then you need to do it as an assignment inside a function, perhaps first thing in the main function:
// Definition of variable
B *x;
int main(void)
{
// Initialization of variable through assignment
x = malloc(sizeof *x);
...
}

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.

Initialize pointer inside struct as compile-time constant

I would like to know what the legal way of defining a constant struct that has a pointer as one of it's elements.
Looking at this post (Initializer element is not constant in C) I can see the following:
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.
My question is if the following is well defined according to the (intersection of the C89 and C99) standard.
The contents of test.h:
#ifndef TEST_H
#define TEST_H
typedef struct _poly {
unsigned long int degree;
signed long int *coeffs;
} poly;
extern const poly my_poly;
extern void print_poly(poly p);
#endif
Contents of test.c:
#include <stdio.h>
#include "test.h"
static signed long int coeffs[3] = {1L, 2L, 3L};
const poly my_poly = {2UL, coeffs};
void print_poly(poly p)
{
/* Irrelevant mumbo-jumbo goes here. */
}
Contents of main.c:
#include "test.h"
int main(void)
{
print_poly(my_poly);
return 0;
}
Compiling on Debian 11 with gcc (and -Wall -Wextra -Wpedantic -std=c89 enabled), clang (with -Weverything -std=c89 enabled), tcc (with -Wall -std=c89 enabled), and pcc (with -std=c89 enabled) produces no warnings and no errors and runs as expected. Is the code:
static signed long int coeffs[3] = {1L, 2L, 3L};
const poly my_poly = {2UL, coeffs};
the correct way to initialize a constant struct that has a pointer as one of its member so that it is a compiler-time constant? It seems to follow the rule that it be an address constant, but I'm not sure.
As the question notes, an initializer may be an address constant.
C 2018 6.6 9 says “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…”
In const poly my_poly = {2UL, coeffs};, coeffs is an array of static storage duration, and it is implicitly converted to a pointer to its first element (per C 2018 6.3.2.1 3). Therefore, the result of the conversion, effectively &coeffs[0], is an address constant and may be used as an initializer.

why cant we assign a value to global variables using an expression in C ?

In the below code snippet , I am trying to assign a value to a global variable using an expression but it gives the error "initializer element is not constant" ,I am unable to get the logic behind this ,please clarify this .
#include<stdio.h>
int a=8;
int b=a+9;
int main()
{
printf("%d",b);
return 0;
}
The reason is that global variables are initialized in compiling time,
and you are trying to initialize b=a+9; as an operation that must be done in execution time.
You can assign a global variable using an expression. But only inside a function. As said by the compiler/linker, outside a function you can initialize variables only to constant. This is because, outside a function, no code can be executed and the variables are initialized to constant value by the compiler/linker at build time. Note that if you don't init the variable (outside a function), the default initialization is to 0.
To make it work you should write
#include<stdio.h>
int a=8;
int b;
int main()
{
b=a+9;
printf("%d",b);
return 0;
}
As b is of arithmetic type and has static storage duration, its initializer has to satisfy the rules of arithmetic constant expressions (C11 §6.6 Expressions):
8 An arithmetic constant expression shall have arithmetic type and
shall only have
operands that are integer constants, floating constants, enumeration constants, character
constants, sizeof expressions whose results are integer constants, and _Alignof
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 or
_Alignof operator.
int b=a+9; doesn't.

Casting pointer to memory buffer to pointer to VLA

in C, I believe the following program is valid: casting a pointer to an allocated memory buffer to an array like this:
#include <stdio.h>
#include <stdlib.h>
#define ARRSIZE 4
int *getPointer(int num){
return malloc(sizeof(int) * num);
}
int main(){
int *pointer = getPointer(ARRSIZE);
int (*arrPointer)[ARRSIZE] = (int(*)[ARRSIZE])pointer;
printf("%d\n", sizeof(*arrPointer) / sizeof((*arrPointer)[0]));
return 0;
}
(this outputs 4).
However, is it safe, in C99, to do this using VLAs?
int arrSize = 4;
int *pointer = getPointer(arrSize);
int (*arrPointer)[arrSize] = (int(*)[arrSize])pointer;
printf("%d\n", sizeof(*arrPointer) / sizeof((*arrPointer)[0]));
return 0;
(also outputs 4).
Is this legit, according to the C99 standard?
It'd be quite strange if it is legit, since this would mean that VLAs effectively enable dynamic type creation, for example, types of the kind type(*)[variable].
Yes, this is legit, and yes, the variably-modified type system is extremely useful. You can use natural array syntax to access a contiguous 2-D array both of whose dimensions were not known until runtime.
It could be called syntactic sugar as there's nothing you can do with these types that you couldn't do without them, but it makes for clean code (in my opinion).
I would say it is valid. The Final version of the C99 standard (cited on Wikipedia) says in paragraph 7.5.2 - Array declarators alinea 5 :
If the size is an expression that is not an integer constant expression: ...
each time it is evaluated it shall have a value greater than zero. The size of each instance
of a variable length array type does not change during its lifetime.
It even explicitely says that it can be used in a sizeof provided the size never changes : Where a size
expression is part of the operand of a sizeof operator and changing the value of the
size expression would not affect the result of the operator, it is unspecified whether or not
the size expression is evaluated.
But the standard also says that this is only allowed in a block scope declarator or a function prototype : An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have
either block scope and no linkage or function prototype scope. If an identifier is declared
to be an object with static storage duration, it shall not have a variable length array type.
And an example later explains that it cannot be used for member fields, even in a block scope :
...
void fvla(int m, int C[m][m]); // valid: VLA with prototype scope
void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA
{
typedef int VLA[m][m]; // valid: block scope typedef VLA
struct tag {
int (*y)[n]; // invalid: y not ordinary identifier
int z[n]; // invalid: z not ordinary identifier
};
...

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