Objective-C 2.0是C的一个适当超集吗?

7

我听说Objective-C是C的一个适当的超集,但Objective-C 2.0也是吗?

我之所以问这个问题是因为要么它不是,要么我误解了“适当的超集”这个术语,因为这段代码是有效的C语法:

#import <stdio.h>

int main () {
    char *nil = "hello";
    printf("%s\n",nil);
}

但在Objective-C 2.0中无法编译。显然,这是一个容易解决的问题,但我正在写一篇论文,觉得应该指出这一点。


3
即使您没有包含任何Objective-C框架或运行时头文件,导致它无法编译的原因是因为您的项目可能具有预编译头,其中包括Foundation框架头文件(以及定义nil的头文件)。 - dreamlax
1
对我来说,它可以通过gcc 4.4编译,并且使用命令行gcc some_file.m -o some_file。因此,虽然可能存在一些有效的C程序不是有效的Objective-C程序,但这个不是其中之一。 - Matthew Flaschen
这个问题指出了一个更加尖锐的反例来驳斥“严格超集”神话:任何使用 id 作为标识符的 C 程序都将无法编译为 Obj-C。 - Fred Foo
2个回答

15

nil 不是关键字。在objc.h [Mac OS X上]中定义了nil(而__DARWIN_NULL实际上只是NULL):

#ifndef nil
#define nil __DARWIN_NULL   /* id of Nil instance */
#endif

也就是说,nil并不真正是编译语言的一部分,而是在编译过程中使用的一种惯例,由系统库延续。

显然,这只是纠结于细节。实际上,你可以编译没有nil的Objective-C源代码。

这就像是在问:“我可以编写一个工具,并将变量命名为deflate,同时仍使用zlib.h接口吗?” 当然可以,但会很丑陋。

实际上,编译器并不会自动包含objc.h。下面是示例:

#include <stdio.h>

int main() {
    int nil = 5;
    fprintf(stdout, "Hello %d\n", nil);
    return 0;
}

如果您删除导入 Foundation 和因此导入 objc.h 的预编译/前缀头文件(在 main.m 中) ,则可以在标准 Foundation 工具项目中编译并运行得很好。(因此,是的,开箱即用,Xcode 模板确实通过导入 Cocoa/Cocoa.h 或 Foundation/Foundation.h 导致导入 objc.h )


1
问题不在于你是否“可以编译没有nil的Objective-C源代码”,而在于你是否能够编译使用nil作为Objective-C的有效C代码。 - Matthew Flaschen
@Matthew 你可以这样做。但是这将非常麻烦,因为你将无法遵循Objective-C的标准模式以及标准运行时或系统库。但是,再次强调,这不是语言问题...而是一个库的问题。 - bbum
如果编译器自动包含它,那么我会说这是一个语言问题。而严格的超集意味着由程序员决定是否以及如何遵循Objective-C模式。 - Matthew Flaschen
2
编译器不会自动包含它。 - bbum
你说得对,@bbum。我认为dreamlax的建议可能是问题所在。 - Matthew Flaschen
显示剩余2条评论

3

Objective-C是C语言的一个合适的超集,因为C语言中的所有内容都可以在Objective-C中使用。

但是,

由于它是一个超集,它添加了一些新类型、定义和指令

这意味着如果您使用保留的定义,比如nil,那么您会遇到严重的问题。

这就是为什么上面的程序无法编译的原因。


+1 - 我知道这条评论有点晚了(这是一篇旧帖子),但你的答案正是我所想的。如果它是一个proper superset,它会添加在子集中不存在的东西。这意味着为子集语言编写的代码可能会在超集语言中被解释得不同,甚至因为你将保留字用作变量名而抛出错误。 - Adam Jones
如果添加新类型、定义或指令会导致以前有效的程序出现错误或更改其语义,那么Objective-C将不再是超集。当然,除非你必须在有效的C中执行不可能的操作才能启用它们。 - Deduplicator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接