您在Objective-C中可以用C做什么?

Rel*_*lla 5 c compare objective-c

您可以在Objective-C中用C(C99标准)做什么?(如果你愿意,可以使用代码示例)

Chu*_*uck 9

我会有点冒昧,不同意其他人.虽然从技术上讲,在一种语言中任何可能的东西在另一种语言中是可能的("可能"意味着"可计算"),但它们在你能够自然轻松地表达的内容上有所不同.计算机可能在响应您用C编写的代码时做同样的事情,但是编写完全不同的代码以使其执行这些操作.

正如其他人所说,Objective-C提供了一个用C编写的完整运行时库,它允许您创建Objective-C数据结构并调用C函数,但执行它的代码将非常冗长,相当迂回且完全必要.在Objective-C中,代码更具说明性,更简洁,更易读.

一般来说,尝试用C编写Objective-C事物只会使你的代码比使用任何一种语言更糟糕.例如,这是一个用Objective-C编写的简单程序:

@interface NumberAdder : NSObject {
    int storedValue;
}

- (id)initWithStoredValue:(int)value;
- (int)resultOfAddingStoredValue:(int)numberToAdd;
@end

@implementation NumberAdder
- (int)resultOfAddingStoredValue:(int)numberToAdd {
    return numberToAdd + storedValue;
}

- (id)initWithStoredValue:(int)value {
    if (!(self = [super init])) return nil;
    storedValue = value;
    return self;
}
@end

int main() {
    id adder = [[NumberAdder alloc] initWithStoredValue:4];
    int result = [adder resultOfAddingStoredValue:3];
    printf("It is %d\n", result);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是用C语言编写的与Objective-C运行时相同的东西(未经过测试,但应该大致正确):

int returnPlusStoredValueImp(id self, SEL _cmd, int arg) {
    int *storedValue = nil;
    object_getInstanceVariable(self, "storedValue", &storedValue)
    return arg + *storedValue;
}

id numberAdderInit(id self, SEL _cmd, int valueToStore) {
    objc_super superInfo = {self, objc_lookupClass("NSObject")};
    self = objc_msgSendSuper(super_info, sel_getName("init"));
    if (!self) return nil;
    object_setInstanceVariable(self, "storedValue", &valueToStore);
    return self;
}

void createNumberAdderClass() __attribute(constructor)__ {
    Class NumberAdder = objc_allocateClassPair(objc_lookupClass("NSObject"), "NumberAdder", 0);
    if (!NumberAdder) return;
    class_addIvar(NumberAdder, "storedValue", sizeof(int), 4, "i"); // I'm actually not sure if the fourth argument is correct, so it's probably wrong, but just take that as a sign of how much this way of coding sucks
    objc_registerClassPair(NumberAdder);
    SEL nameOfPlusStoredValue = sel_registerName("resultOfAddingStoredValue:");
    SEL nameOfInit = sel_registerName("initWithStoredValue:");
    class_addMethod(NumberAdder, nameOfPlusStoredValue, returnPlusStoredValueImp, "i@:i");
    class_addMethod(NumberAdder, nameOfInit, numberAdderInit, "@@:i");
}

int main() {
    id adder = objc_msgSend(objc_lookupClass("NumberAdder"), sel_getName"alloc");
    adder = objc_msgSend(adder, sel_getName("initWithStoredValue:"), 4);
    int result = (int)objc_msgSend(adder, sel_getName("resultOfAddingStoredValue:"), 3);
    printf("It is %d\n", result);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


小智 8

绝对没有.Objective-C的OO功能实现为用C编写的小型运行时库.

虽然一些评论者可能会指出Objective-C有块而C没有,这实际上是Objective-C使用的C的GCC/LLVM扩展,但它不是ObjC功能.

  • 块 - 在Mac OS X中实现 - 绝对不需要可执行堆栈.这是他们设计的要求. (3认同)
  • 一个通常值得避免使用的功能,因为它有时需要一个可执行的堆栈(gcc在堆栈上生成一个蹦床来恢复堆栈帧以便范围嵌套工作,蹦床是一个小功能,可以做一些魔术:P )可执行堆栈可能不可用...例如打开NX(gcc可能使用madvise或其他东西,所以它仍然可以工作......也许) (2认同)
  • 为了增加Graham的精心设计的点,小型运行时库甚至可以作为一组允许使用的C函数公开.换句话说,您甚至可以在不使用Objective-C的情况下使用Objective-C库.请参阅此处:http://developer.apple.com/mac/library/documentation/cocoa/reference/objcruntimeref/Reference/reference.html (2认同)