Compiler error: "initializer element is not a compile-time constant"

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
137800 次浏览

Because you are asking the compiler to initialize a static variable with code that is inherently dynamic.

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

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

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

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

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.

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