When compiling this code, I get the error «initializer element is not a compile-time constant». Can anyone explain why?
#import "PreferencesController.h"
@implementation PreferencesController
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
NSImage* imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];//error here
jscs
63.6k13 gold badges150 silver badges194 bronze badges
asked May 26, 2011 at 18:07
When you define a variable outside the scope of a function, that variable’s value is actually written into your executable file. This means you can only use a constant value. Since you don’t know everything about the runtime environment at compile time (which classes are available, what is their structure, etc.), you cannot create objective c objects until runtime, with the exception of constant strings, which are given a specific structure and guaranteed to stay that way. What you should do is initialize the variable to nil and use +initialize
to create your image. initialize
is a class method which will be called before any other method is called on your class.
Example:
NSImage *imageSegment = nil;
+ (void)initialize {
if(!imageSegment)
imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
}
- (id)init {
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
answered May 26, 2011 at 18:22
ughoavgfhwughoavgfhw
39.7k6 gold badges101 silver badges123 bronze badges
6
A global variable has to be initialized to a constant value, like 4
or 0.0
or @"constant string"
or nil
. A object constructor, such as init
, does not return a constant value.
If you want to have a global variable, you should initialize it to nil
and then return it using a class method:
NSImage *segment = nil;
+ (NSImage *)imageSegment
{
if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
return segment;
}
answered May 26, 2011 at 18:14
mipadimipadi
396k89 gold badges523 silver badges479 bronze badges
2
Because you are asking the compiler to initialize a static variable with code that is inherently dynamic.
answered May 26, 2011 at 18:14
bbumbbum
162k23 gold badges271 silver badges359 bronze badges
The reason is that your are defining your imageSegment
outside of a function in your source code (static variable).
In such cases, the initialization cannot include execution of code, like calling a function or allocation a class. Initializer must be a constant whose value is known at compile time.
You can then initialize your static variable inside of your init
method (if you postpone its declaration to init).
answered May 26, 2011 at 18:15
sergiosergio
68.8k11 gold badges102 silver badges122 bronze badges
2
You can certainly #define a macro as shown below. The compiler will replace «IMAGE_SEGMENT» with its value before compilation. While you will achieve defining a global lookup for your array, it is not the same as a global variable. When the macro is expanded, it works just like inline code and so a new image is created each time. So if you are careful in where you use the macro, then you would have effectively achieved creating a global variable.
#define IMAGE_SEGMENT [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
Then use it where you need it as shown below. Each time the below code is executed, a new object is created with a new memory pointer.
imageSegment = IMAGE_SEGMENT
answered Jun 2, 2015 at 15:38
You can use the static singleton approach with dispatch_once
:
#define STATIC_VAR(type, code) ^type() {
static type object;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object = code;
});
return object;
};
#define let __auto_type const
let imageSegment = STATIC_VAR(UIImage*, [[UIImage alloc] initWithContentsOfFile:@"image.jpg"]);
let imageRect = STATIC_VAR(CGRect, CGRectMake(0, 0, 100, 100));
// How to use:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageView.image = imageSegment();
self.imageView.frame = imageRect();
}
It is thread safe, works lazily with any type and makes only a single instance.
answered Aug 12, 2021 at 10:10
iUriiiUrii
10.9k1 gold badge31 silver badges44 bronze badges
I got this error while practicing C language, my code that I was trying to run was this
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *name;
int age;
} person;
person *p = (person *)malloc(sizeof(person));
and I realized while reading answers, that in C, I should have main function, which I forgot to use, so put the person code in main function, thus removing the error as follows
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *name;
int age;
} person;
int main()
{
person *p = (person *)malloc(sizeof(person));
return 0;
}
answered Mar 18, 2022 at 7:48
I have been looking for answers but could not find anything to make this code run. I get av[1]
highlighted by the compiler in the main function when declaring:
static char const *str = av[1];
Here is the code I tried to run with gcc:
#include <stdio.h>
#include <stdlib.h>
char *ft_strjoin(char const *s1, char const *s2);
void fct(char **av)
{
static char const *str = av[1];
str = ft_strjoin(av[1], av[1]);
printf("%sn", str);
}
int main(int ac, char **av)
{
fct(&av[1]);
fct(&av[1]);
fct(&av[1]);
fct(&av[1]);
fct(&av[1]);
fct(&av[1]);
}
I found this interesting but I still don’t get it and don’t know how to run this code.
Sourav Ghosh
133k16 gold badges183 silver badges261 bronze badges
asked Dec 24, 2015 at 9:09
3
Quoting C11
, §6.7.9, Initialization
All the expressions in an initializer for an object that has static or thread storage duration
shall be constant expressions or string literals.
In your code,
static char const *str = av[1];
av[1]
is not a compile time constant value (i.e., not a constant expression). Hence the error.
You need to remove static
from str
to avoid the issue.
fuz
87.8k24 gold badges196 silver badges349 bronze badges
answered Dec 24, 2015 at 9:20
Sourav GhoshSourav Ghosh
133k16 gold badges183 silver badges261 bronze badges
static
variables need to be initialised with a compile time constants (constant literals). av[1]
will be calculated at runtime and that’s why you are getting the error message.
answered Dec 24, 2015 at 9:15
hacckshaccks
104k25 gold badges175 silver badges264 bronze badges
You could simulate that behaviour by writing:
static const char *str;
static bool already;
if ( !already )
{
str = av[1];
++already;
}
However this would be redundant compared to the solution of:
const char *str;
because you immediately overwrite that value anyway with the return value of your function.
(Also you pass the same argument in every call, so even if you used str
, it still doesn’t need to be static).
answered Dec 24, 2015 at 9:34
M.MM.M
138k21 gold badges204 silver badges357 bronze badges
Initializer element is not constant define error might occur while using GCC 7.4.0 due to its lack of support for the const qualifier. Therefore, assigning incorrectly defined or improperly placed constants to the static variables results as this error.
But you don’t need to worry even if you can’t figure out the problem in your code all alone because this article will assist you in every aspect that relates to the same error. Read the entire post to discover your difficult-to-locate mistakes and correct them to eliminate the error.
Contents
- Initializer Element Is Not Constant: What Are the Causes?
- – Const and GCC 7.4.0
- – You Have an Unclear Concept of Constants
- – Your Constants Aren’t Placed Inside the Main Function
- – You Haven’t Initialized a Static Variable With a Constant
- Solutions for the Initializer Element Is Not Constant Error
- – Using #define Will Make Things Work
- – Update To GCC 8.1 or a Later Version
- – Assign Correct Values To the Constants
- – Add the Difficult-to-evaluate Code Inside a Function
- – Add the Constants Inside the Main Function
- Conclusion
- References
Initializer Element Is Not Constant: What Are the Causes?
The cause of the initializer element is not constant error is that the program not initializing the static variable with a constant. Other problems include using the const qualifier with GCC 7.4.0 compiler, a weak concept of constants, or placing the constants outside the main() function.
– Const and GCC 7.4.0
If you are using GCC 7.4.0 and you try to create constants by using the const qualifier, the given error will show up on your screen. You must know that the const-qualified objects are not considered constants by GCC 7.4.0.
For example, you have created a constant of int data type. Its value equals 50. But as soon as you try to use it to initialize an object with static storage duration, you get an error stating that the initializer element is not constant define.
Here is the erroneous code snippet that’ll throw an error when compiled using GCC 7.4.0:
static int R = H;
– You Have an Unclear Concept of Constants
If you aren’t clear about the valid values that must be assigned to the constants, you might receive the same error at some point in your program. Assigning invalid values to the constants isn’t a good practice. Such values aren’t acceptable and can hinder the creation of constants.
For example, you are trying to make a large object a constant. It won’t be possible to do it. Consequently, you’ll get the stated error when you use the same constant to initialize a static storage duration.
– Your Constants Aren’t Placed Inside the Main Function
The constants placed outside your main function and assigned to your static variables can lead to the initializer element is not constant static error. It means that it’s not only about the constant values, but the position of the constants is important too.
Moreover, the compiler finds it difficult to evaluate the constant values and assign them to another variable. Thus, if you try to assign a variable to another at compile-time, you’ll see the initializer element is not constant struct on your screen.
Imagine that you have defined two constants and assigned their sum to a static variable. But an error pops up when you try to compile the code.
Here is the code block that might result in the given error:
const int NUM2 = 80;
static int RES = NUM1 + NUM2;
– You Haven’t Initialized a Static Variable With a Constant
Initializing a static storage duration with a constant expression or with an aggregate initializer containing a constant expression is crucial. If you do it any other way, the error under consideration will pop up. Thus, you can not assign a non-constant value to a static variable.
Think about it this way. You have an int variable. Now, you want to create a new static variable and assign the same number to it. In this case, you’ll receive the initializer element is not a compile-time constant error.
The following code snippet depicts the above scenario to help you out:
static int LENGTH = NUM;
Solutions for the Initializer Element Is Not Constant Error
You can solve the initializer element is not constant calloc error by creating the constants perfectly and initializing the static variables with the constants. You can create perfect constants by using #define instead of the const qualifier with GCC 7.4.0 or updating to GCC 8.1.
– Using #define Will Make Things Work
As in GCC 7.4.0, the const qualifier doesn’t help in creating constants and can cause the initializer element is not constant malloc. Thus, you should use #define to create named constants. This way, you won’t even need to position the constants inside the main function.
So, all that you’ll need to do is to opt for the method that uses #define to create constants. Consequently, the constants will be created perfectly, and the reason for the given error will be vanished leading to the removal of the given error.
Look below to know how to use #define.
– Update To GCC 8.1 or a Later Version
The const qualifier is supported in the GCC 8.1 and later versions. Hence, if you update your compiler, you’ll see the stated error go away. Also, you’ll not need to make changes to your code. You can get the update by changing your tool chain to gnu-tools-for-stm32.9-2020-q2-update.
The given tool chain uses GCC v9.3.1, which is sufficient to compile a code block similar to the one shared below.
static int R = H;
– Assign Correct Values To the Constants
The constants can take up literals, such as strings, characters, integers, float values, and enumerations. Besides this, a constant expression must evaluate to a null pointer constant, an arithmetic constant expression, or an address constant. Once you fix the constant value, the error should go away.
Also, note that a constant expression can evaluate to an address constant for an object type minus or plus an integer constant expression.
– Add the Difficult-to-evaluate Code Inside a Function
You should add the difficult-to-evaluate code inside a function to resolve the initializer element is not constant fopen error. This way, the compiler won’t get confused, and eventually, you’ll not get the said error.
Here is the code that will work just the way you want.
int func1(){
const int NUM1 = 40;
const int NUM2 = 80;
static int RES = NUM1 + NUM2;
}
– Add the Constants Inside the Main Function
Adding the constants inside the main function will help resolve the initializer element is not constant array error. The main function is considered the starting point of your program. So, it would be best to include the constants inside the same as an attempt to confirm their creation.
The following block of code creates a constant and a static variable inside the main function to avoid all the conflicts of the compiler and the code.
const int AREA = 50;
static int VAL = AREA;
}
Conclusion
Hopefully, The initializer element is not constant error is no more frustrating because you have learned about the various issues that can lead to faulty constants. Plus, you have found out the ways to create the constants that’ll help in the initialization of the static variables.
Please read the list of crucial points from this post to clarify your remaining doubts:
- You can use #define to create the constants while running GCC 7.4.0 to resolve the error immediately.
- If you want to use the const qualifier, then you’ll need to update your compiler GCC 8.1 or a newer version and get rid of the error.
- Ensure to provide only literals to the constants, which include strings, integers, characters, float values, and enumerations.
- Add the code that is difficult to evaluate inside a function to satisfy the compiler and stop it from showing you the given error.
- You should add the constants inside the main() function to confirm their creation and kick away the error in the title.
So, the better constants you create and the better you understand the relationship between the constants and the static variables, the more efficient you’ll be at solving the same error.
References
- https://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w
- https://cboard.cprogramming.com/c-programming/176605-initializer-element-not-constant.html
- https://stackoverflow.com/questions/12750796/initializer-element-is-not-constant-in-c?noredirect=1&lq=1
- Author
- Recent Posts
Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL. Meet The Team
You have the right idea behind how the code works, it’s just your English to C needs some practice (understandably).
int main(void);
This is, as its name suggests, the «main» method. Essentially, when you say to run the program, it looks for main(void) and goes from there. Therefore, all your other code should be inside this function, Which will take care of error number one.
int main(void)
{
// code goes here
}
Next up: The do-while. First, after the closing )
in the while there should be a ;
. Next, !>
and !<
aren’t recognized by C. Your options are ==
, !=
, >
and <
. So instead of saying «while n isn’t greater than 0 and isn’t less than 23», instead try «while n is outside the boundries (of 0 and 23)».
Let me know if you could use more guidance, particularly on the second part. You’re doing well so far!
При компиляции этого кода я получаю ошибку «элемент инициализации не является константой времени компиляции». Может кто-нибудь объяснить, почему?
#import "PreferencesController.h"
@implementation PreferencesController
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
NSImage* imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];//error here
Ответ 1
Когда вы определяете переменную вне области действия функции, это значение переменной фактически записывается в ваш исполняемый файл. Это означает, что вы можете использовать только постоянное значение. Поскольку вы не знаете все о среде выполнения во время компиляции (какие классы доступны, какова их структура и т.д.), Вы не можете создавать объектные объекты c до выполнения, за исключением постоянных строк, которым заданы конкретные структуры и гарантированно останется таким образом. Что вам нужно сделать, это инициализировать переменную до нуля и использовать +initialize
для создания вашего изображения. initialize
— это метод класса, который будет вызываться до вызова любого другого метода в ваш класс.
Пример:
NSImage *imageSegment = nil;
+ (void)initialize {
if(!imageSegment)
imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
}
- (id)init {
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
Ответ 2
Глобальная переменная должна быть инициализирована с постоянным значением, например 4
или 0.0
или @"constant string"
или nil
. Конструктор объекта, такой как init
, не возвращает постоянное значение.
Если вы хотите иметь глобальную переменную, вы должны инициализировать ее до nil
, а затем вернуть ее с помощью метода класса:
NSImage *segment = nil;
+ (NSImage *)imageSegment
{
if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
return segment;
}
Ответ 3
Потому что вы просите компилятор инициализировать статическую переменную с кодом, который по своей сути является динамическим.
Ответ 4
Причина в том, что вы определяете свой imageSegment
вне функции в исходном коде (статическая переменная).
В таких случаях инициализация не может включать выполнение кода, например вызов функции или распределение класса. Инициализатор должен быть константой, значение которой известно во время компиляции.
Затем вы можете инициализировать свою статическую переменную внутри вашего метода init
(если вы отложите ее объявление до init).
Ответ 5
Вы можете указать #define макрос, как показано ниже. Компилятор заменит «IMAGE_SEGMENT» своим значением перед компиляцией. Хотя вы достигнете определения глобального поиска для вашего массива, это не то же самое, что глобальная переменная. Когда макрос расширяется, он работает так же, как встроенный код, и каждый раз создается новое изображение. Поэтому, если вы будете осторожны в том, где используете макрос, вы бы эффективно достигли создания глобальной переменной.
#define IMAGE_SEGMENT [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
Затем используйте его там, где вам это нужно, как показано ниже. Каждый раз, когда выполняется следующий код, создается новый объект с новым указателем памяти.
imageSegment = IMAGE_SEGMENT