1

I want to declare a simple array of structures This is my code... but it didn't work:

@implementation GLPlane{
    GLKVector2 *vertices;
}

-(id)init{

    if(self = [super init]){
        vertices = {<---- This operation seems to be not allowed. 
            GLKVector2Make(0.0f, 0.5f),
            GLKVector2Make(-0.5f, 0.5f),
            GLKVector2Make(0.0f, 0.0f)
        };
    }
    return self;

}

Where is the problem?

If I write the init function that way, using a temporary array it works

-(id)init{

    if(self = [super init]){
        GLKVector2 tempArray[] = {
            GLKVector2Make(0.0f, 0.5f),
            GLKVector2Make(-0.5f, 0.5f),
            GLKVector2Make(0.0f, 0.0f)
        };

        vertices = tempArray;
    }

    return self;
}
5
  • 1
    Assignment is not initialization. Commented Aug 3, 2013 at 14:15
  • I have added some more info. The error is Expected Expression Commented Aug 3, 2013 at 14:16
  • Sorry guys but way these 2 down vote? Commented Aug 3, 2013 at 14:17
  • 1
    Note that in your second example vertices would be a pointer to a local stack variable and therefore be invalid as soon as the init method returns. Commented Aug 3, 2013 at 14:27
  • So isn't there a way to store this struct in the object interface? Commented Aug 3, 2013 at 14:31

4 Answers 4

3
GLKVector2 *vertices;

is a pointer, not an array. You have to allocate memory first and then you can assign values:

vertices = calloc(3, sizeof(GLKVector2));
vertices[0] = GLKVector2Make(0.0f, 0.5f);
vertices[1] = GLKVector2Make(-0.5f, 0.5f);
vertices[2] = GLKVector2Make(0.0f, 0.0f);

ARC does not manage this type of allocations, so you should free the memory in dealloc:

- (void)dealloc 
{
    free(vertices);
}

Note that your second example compiles, but is not correct: vertices would be a pointer to a local stack variable and therefore be invalid as soon as the init method returns.

Sign up to request clarification or add additional context in comments.

Comments

1

You should use NSValue class:

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/Reference/Reference.html

You can wrap your structure to NSValue class object and then add it to array

Convert:

NSValue *anObj = [NSValue value:&vector withObjCType:@encode(GLKVector2)];
NSArray *array = [NSArray arrayWithObjects:anObj, nil];

Unconvert:

NSValue *anObj = [array objectAtIndex:0];
GLKVector2 vector;
[anObj getValue:&vector];

1 Comment

For performance based OpenGL calls this is a terrible idea. It's infinitely slower than a pure C array created with malloc.
1

First and foremost, what you are doing will lead to corrupted memory, don't do it. You are creating an array on the stack and assigning it to a variable whose lifetime will outlive the stack frame wherein the data is valid. You need to malloc the space (remember to free it in dealloc!), and initialize it one element at a time (or create a temporary array and copy it). Or, even better, use Igor's suggestion of an NSArray.

Now, to clarify the array behavior that was confusing you (Note that these are based on the code you posted and so are subject to the stack assignment problem described above):

    vertices = {<---- This operation seems to be not allowed. 
        GLKVector2Make(0.0f, 0.5f),
        GLKVector2Make(-0.5f, 0.5f),
        GLKVector2Make(0.0f, 0.0f)
    };

The reason this is not allowed is that the compiler doesn't know what type you expect that array to be (C and Objective C don't do type inference). What you can do is tell the compiler what type the array is:

    vertices = (GLKVector2[]){
        GLKVector2Make(0.0f, 0.5f),
        GLKVector2Make(-0.5f, 0.5f),
        GLKVector2Make(0.0f, 0.0f)
    };

As a special exception, however, when you are initializing an array in its declaration, the compiler does assume it is the type it is currently being declared as, which is why this works:

    GLKVector2 tempArray[] = {
        GLKVector2Make(0.0f, 0.5f),
        GLKVector2Make(-0.5f, 0.5f),
        GLKVector2Make(0.0f, 0.0f)
    };

    vertices = tempArray;

2 Comments

In both of your last examples, note that that array will be allocated on the stack, and after the stack frame 'pops', you will loose your array.
@RichardJ.RossIII Yes, the examples were for explanation, not the fix, which I described in the first paragraph. I've added clarification to that effect.
0

The problem you are facing doesn't have anything to do with your structs and is in fact a problem with the way that your array is initialized. When creating arrays using this notation:

int myArr[] = {1, 3, 4, 5};

It only works when declaring the array and initializing it at the same time. This is the case in Java, C, C++ and Objective-C. However you have one more problem and that is that you declare a pointer and they you try to add items to it. But a pointer is not an array, for example:

int myOtherArr[5];
int *mySecondArr;

myOtherArr is not the same as mySecondArr. In order to use the pointer as an array, you have to allocate the memory as an array using malloc or new or something similar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.