【问题标题】:What you can't do in C that you can do in Objective-C?在 C 中你不能在 Objective-C 中做的事情是什么?
【发布时间】:2010-06-14 14:42:37
【问题描述】:

在 C(C99 标准)中不能做什么,而在 Objective-C 中可以做什么? (请提供代码示例)

【问题讨论】:

  • 您的意思是“Objective-C 独有的语法是什么”?
  • 它们都是图灵完备的......
  • 轻松进行面向对象编程? (而在 C 中会更难......)
  • 为什么是 C99 标准?

标签: objective-c c compare


【解决方案1】:

我会有点自以为是,不同意其他人的观点。虽然从技术上讲,在一种语言中任何可能的事情在另一种语言中都是可能的(其中“可能”的意思是“可计算的”),但它们在您可以自然轻松表达的内容上有所不同。计算机可能会为响应您用 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;
}

这是用 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;
}

【讨论】:

  • +1 表示采取强硬路线并进行展示。很好的答案。
  • 实际上 +2,因为围绕计算机语言的重点是这个(或周围),否则我们都会使用静态汇编,因为不需要更高的“语言结构”。
【解决方案2】:

绝对没有。 Objective-C 的 OO 特性被实现为一个用 C 编写的小型运行时库。

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

【讨论】:

  • 一个经常值得避免使用的特性,因为它有时需要一个可执行堆栈(gcc 在堆栈上生成一个蹦床以恢复堆栈帧,以便范围嵌套工作,蹦床是有一些魔力的小函数 :P) 可执行堆栈可能不可用...例如打开 NX(gcc 可能使用 madvise 或其他东西,所以它仍然可以工作...也许)
  • 为了补充 Graham 的精辟观点,小型运行时库甚至公开为一组您可以使用的 C 函数。换句话说,你甚至可以在不使用 Objective-C 的情况下使用 Objective-C 库。见这里:developer.apple.com/mac/library/documentation/cocoa/reference/…
  • 块——在 Mac OS X 中实现——绝对需要一个可执行堆栈。这是他们设计中的要求。
  • 使用运行时库不允许像在Objective-C 中进行的面向对象编码那样的事情。您可以创建相同的数据结构并调用相同的函数,但这就像拥抱某人和构建一个机器人为您拥抱他们之间的区别。
  • @Chuck -- 使用运行时库,您可以动态组合类、进行继承、进行方法分派(使用继承)等...您真的可以完全用 C 语言进行 OO 编程. 事实上,它会是一个完整的 PITA。
【解决方案3】:

正如 Graham 所说——在 Objective-C 中绝对没有什么是在 C 中不能完成的。当然,在 C 中也没有什么是你可以做的,那是不可能的组装完成。这只是打字的问题。

(我希望程序集的提及足以表明,不,我并不是在暗示用纯 C 编写 OO 模式是一件很有意义的事情......)

还有一些额外的兴趣点:

  • Objective-C 最初是作为一种预处理器,将 Objective-C 代码转换为标准 C 编译器可以编译的 C 代码。也就是说,Objective-C 最初从未被直接编译,而是直接翻译成 C 语言,然后编译。

  • Objective-C 对象可以被认为是 C 结构,其中结构中的第一个条目——isa——始终是指向元数据的指针——Class——描述结构/实例。

  • 块是对 C 的扩展,现在在 WG-14(C 标准委员会)中提议作为 C 语言的补充。 Apple 实现的块绝对需要可执行堆栈。这是他们设计中的硬性要求。

  • LLVM 有一个重写器,它实际上可以将 Objective-C 重写为 C,并且显然已被用于在 Xbox 360 游戏中启用 Objective-C 编码(请参阅http://permalink.gmane.org/gmane.comp.compilers.llvm.devel/31996)。

【讨论】:

  • 不仅仅是打字的问题。 HL 语法和不同的范式有助于“以不同的方式思考”,并改变对问题的看法(从而改变您找到解决方案的方式)。它们是工具,没有它们,您将无法达到同样的高度。你不能认为建造一座大教堂就足够了很快你就会重新构建/编写那些你已经拥有的工具......但是一旦你这样做了,你就会确认你需要它们继续下去。循环
  • @ShinTakezou 我相信你和我意见一致。我从来没有暗示用纯 C 编写 OO 代码是一个合理的解决方案。
【解决方案4】:

没有这样的事情。一般来说,你可以用任何编程语言编写任何东西。

【讨论】:

  • 只要“anything”省略了很多东西。
  • 太棒了,请您发布您对停机问题的解决方案。 en.wikipedia.org/wiki/Halting_problem
  • 真的是 Sjoerd 吗?猜猜我们只需要一种编程语言! /讽刺
  • +1 因为这是其他答案中已经说过的,没有讽刺,也没有提出停止问题。语境化(总是必要的)使断言变得简单。(我们生活在一个有限的世界中,计算机是由人类制造的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 2014-02-25
相关资源
最近更新 更多