0

I created a C array like this:

unsigned char colorComps[] = {2, 3, 22,   55, 9, 1};

which I want to pass to an initializer of an Objective-C object.

So I think I have to put the array on the heap:

size_t arrayByteSize = numColorCompVals * sizeof(unsigned char);
unsigned char *colorCompsHeap = (unsigned char*)malloc(arrayByteSize);

Then I have to write my first "stack memory array" to the heap array in for loop:

for (int i = 0; i < numColorCompVals; i++) {
   colorCompsHeap[i] = colorComps[i];
}

Side question: Is there a more elegant solution to avoid the for-loop step?

And then I pass it to the method:

defined as

- (id)initWithColorCompsC:(unsigned char *)colorCompsHeap;

TheObject *obj = [[TheObject alloc] initWithColorCompsC:colorCompsHeap];

TheObject has a property to hold the C-array:

@property (nonatomic, assign) unsigned char *colorComps;

And in -dealloc I free it:

free(_colorComps);

This is in theory. I use ARC for Objective-C. Am I doing this correct or is there a better way?

1
  • You'd probably be better off allocating and copying the array in the constructor. Commented Aug 7, 2013 at 14:29

3 Answers 3

2

This seems fine, however...

  1. Don't cast the return value of malloc();
  2. and don't reinvent memcpy(). Instead of your for loop, write memcpy(dest, src, size).
Sign up to request clarification or add additional context in comments.

8 Comments

Even better - use memcpy with a C99 compound literal array. Much more consise.
@RichardJ.RossIII Yeah, I am aware of them (I just didn't think this was the question here.)
Richard can you explain what you mean with a C99 compound literal array?
According to the documentation memcpy is for chars. What about other data types? tutorialspoint.com/c_standard_library/c_function_memcpy.htm
@ProudMember: memcpy copies data. It is not picky about data type. The documentation you link to clearly specifies that it takes void * arguments, not char or char *.
|
1

If TheObject is going to free the array, then its init method should be the one to make the copy, NOT the caller. That way each instance of TheObject make its own copy and frees its own copy, it owns that copy.

Also, then it doesn't matter where the parameter to the init comes from, stack or heap. It won't matter if the init method makes a copy of it.

Use memcpy to make the copy, with sizeof the destination array, like this for the .m file:

@interface PTTEST ()
@property (nonatomic, assign) unsigned char *colorComps;
@end

@implementation PTTEST

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

- (id)initWithColorCompsC:(unsigned char *)colorComps
       numberOfColorComps:(unsigned)numberOfColorComps
{
    self = [super init];
    if (self) {
        // compute size based on sizeof the first element (in case
        // the element type get changed later, this still works right)
        size_t arraySize = sizeof(colorComps[0]) * numberOfColorComps;

        _colorComps = malloc(arraySize);

        memcpy(_colorComps, colorComps, arraySize);
    }
    return self;
}

@end

6 Comments

One more question: Why wouldn't size_t arraySize = sizeof(colorComps) work?
@ProudMember because that returns the size of the pointer, not the array itself.
And how about sizeof(&colorComps)?
@H2CO3 Care to explain?
@ProudMember Explain what?
|
0

Doesn't seems correct to me, you are filling colorCompsHeap(an array of unsigned chars) with the values of colorComps[] (an array of doubles)

unsigned char u = 0.2;

printf("%f\n", (double)u);

Outputs 0.000000

1 Comment

@DavidRF Then it was someone else, and he still didn't leave any explanation.

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.