2

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.

battyman17
  • 65
  • 6
  • Is it the real code ? Because `member 1`in a structure doiesn't mean anything – Guillaume Petitjean Dec 19 '19 at 09:00
  • Exactly the same code with `int a`, `int n` works, please, provide better information about types of members. –  Dec 19 '19 at 09:02
  • 1
    Please try to create [mcve] to show us, preferably something that we can copy-paste (without editing) and replicate the problem ourselves. – Some programmer dude Dec 19 '19 at 09:05
  • 1
    where does the error occur? are you including stdlib.h? Try changing `typedef struct A {` to `typedef struct {` – Maxxik CZ Dec 19 '19 at 09:12
  • The edited code also works good for me... :/ –  Dec 19 '19 at 09:13
  • This compiles, please show more code that's not where the error is. – BobRun Dec 19 '19 at 09:14
  • @BobRun After this I am just using this pointer assign values to the structure first 2 members in one function and other 2 members in a different function. Then with those values I am doing some comparisons in a separate function. But the error is pointing to this line `B *x = (B*)malloc(sizeof(B));` . Also I forgot to mention, the structure is declared in a .h file and this structure pointer I am defining is in a .c file. I don't think that can be the cause of this error. – battyman17 Dec 19 '19 at 09:29
  • 2
    Are you doing `B *x = (B*)malloc(sizeof(B));` in the *global* scope, or inside a function? That should really be part of your [mcve]. – Some programmer dude Dec 19 '19 at 09:35
  • By the way (but unrelated to your issue) in C you [should not cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Dec 19 '19 at 09:37
  • @Someprogrammerdude I have mentioned in my question that I am decalaring that structure pointer globally. – battyman17 Dec 19 '19 at 09:38
  • @Someprogrammerdude Even without the casting, still getting the same issue. – battyman17 Dec 19 '19 at 09:39
  • `B *x = (B*)malloc(sizeof(B));` : doing this in global scope is rather pointless anyway, just declare the variable as normal global: `B Foo;` and later at some point `B *x = &Foo;`. – Jabberwocky Dec 19 '19 at 09:48

2 Answers2

4

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

  1. 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.

LPs
  • 16,045
  • 8
  • 30
  • 61
  • 1
    Thanks for the detailed explanation. – battyman17 Dec 19 '19 at 09:55
  • I still have a doubt. If I declare the structure pointer globally like this `B *x;` and inside all the functions which will use this variable, I will allocate memory like this--> `x = malloc(sizeof(B));` , so should I have to do `free(x)` in all the functions ? I have to mention that these functions would be called iteratively multiple times. – battyman17 Dec 19 '19 at 10:04
  • Each time you allocate something with `malloc` you are consuming/allocating heap memory. If you don't `free` the allocated memory and overwrite the current value of the global variable `x` you are loosing the pointer to the allocated memory and that memory will be lost. So: always `free` the `m-allocated` memory before to `re malloc` new memory – LPs Dec 19 '19 at 10:07
  • Thanks for this information. – battyman17 Dec 19 '19 at 10:08
  • Alternatively you can use [realloc](https://www.geeksforgeeks.org/g-fact-66/) standard function – LPs Dec 19 '19 at 10:09
  • Ok will try out that too. Thanks. – battyman17 Dec 19 '19 at 10:12
3

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

    ...
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621