NSArray к массиву C

Это особенность, и на самом деле она очень важна. Это сводится к свойству, известному как параметричность в теории языка программирования. Грубо говоря, это означает, что оценка никогда не должна зависеть от типов, которые являются переменными во время компиляции. Вы не можете посмотреть на значение, если вы не знаете его конкретный тип статически.

Почему это хорошо? Это дает гораздо более сильные инварианты о программах. Например, по одному только типу вы знаете, что a -> a должна быть тождественной функцией (или расходиться). Подобные «свободные теоремы» применимы ко многим другим полиморфным функциям. Параметричность также является основой для более продвинутых методов абстракции на основе типов. Например, тип ST s a в Haskell (монада состояний) и тип соответствующей функции runST полагаются на параметрический s. Это гарантирует, что у запущенной функции нет возможности связываться с внутренним представлением состояния.

Это также важно для эффективной реализации. Программа не должна передавать дорогостоящую информацию о типах во время выполнения ( стирание типов ), и компилятор может выбирать перекрывающиеся представления для разных типов. Как пример последнего, 0 и False и () и [] все представлены 0 во время выполнения. Это было бы невозможно, если бы была разрешена такая функция, как ваша.

18
задан pnandy 18 June 2009 в 09:25
поделиться

3 ответа

Ответ зависит от природы C-массива.

Если вам нужно заполнить массив примитивных значений известной длины, вы можете сделать что-то вроде этого:

NSArray* nsArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],
                                             [NSNumber numberWithInt:2],
                                             nil];
int cArray[2];

// Fill C-array with ints
int count = [nsArray count];

for (int i = 0; i < count; ++i) {
    cArray[i] = [[nsArray objectAtIndex:i] intValue];
}

// Do stuff with the C-array
NSLog(@"%d %d", cArray[0], cArray[1]);

Вот пример, в котором мы хотим создать новый C-массив из NSArray , сохраняя элементы массива как объекты Obj-C:

NSArray* nsArray = [NSArray arrayWithObjects:@"First", @"Second", nil];

// Make a C-array
int count = [nsArray count];
NSString** cArray = malloc(sizeof(NSString*) * count);

for (int i = 0; i < count; ++i) {
    cArray[i] = [nsArray objectAtIndex:i];
    [cArray[i] retain];    // C-arrays don't automatically retain contents
}

// Do stuff with the C-array
for (int i = 0; i < count; ++i) {
    NSLog(cArray[i]);
}

// Free the C-array's memory
for (int i = 0; i < count; ++i) {
    [cArray[i] release];
}
free(cArray);

Или вы можете захотеть nil - завершите массив вместо того, чтобы передавать его длину:

// Make a nil-terminated C-array
int count = [nsArray count];
NSString** cArray = malloc(sizeof(NSString*) * (count + 1));

for (int i = 0; i < count; ++i) {
    cArray[i] = [nsArray objectAtIndex:i];
    [cArray[i] retain];    // C-arrays don't automatically retain contents
}

cArray[count] = nil;

// Do stuff with the C-array
for (NSString** item = cArray; *item; ++item) {
    NSLog(*item);
}

// Free the C-array's memory
for (NSString** item = cArray; *item; ++item) {
    [*item release];
}
free(cArray);
39
ответ дан 30 November 2019 в 06:29
поделиться

Я бы посоветовал преобразовать себя, например:

NSArray * myArray;

... // code feeding myArray

id table[ [myArray count] ];

int i = 0;
for (id item in myArray)
{
    table[i++] = item;
}
4
ответ дан 30 November 2019 в 06:29
поделиться

NSArray имеет метод -getObjects: range: для создания C-массива для поддиапазона массива.

Пример:

NSArray *someArray = /* .... */;
NSRange copyRange = NSMakeRange(0, [someArray count]);
id *cArray = malloc(sizeof(id *) * copyRange.length);

[someArray getObjects:cArray range:copyRange];

/* use cArray somewhere */

free(cArray);
6
ответ дан 30 November 2019 в 06:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: