点(“.")运算符和箭头(“->")运算符在 C 与 Objective-C 中的使用 [英] Dot (".") operator and arrow ("->") operator use in C vs. Objective-C

查看:40
本文介绍了点(“.")运算符和箭头(“->")运算符在 C 与 Objective-C 中的使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图围绕 C 与 Objective-C 在用法和语法上的一些差异进行总结.特别是,我想知道 C 与 Objective-C 中点运算符和箭头运算符的用法有何不同(以及为什么).这是一个简单的例子.

I'm trying to wrap my head around some of the differences in usage and syntax in C vs. Objective-C. In particular, I want to know how (and why) the usage differs for the dot operator and the arrow operator in C vs. Objective-C. Here is a simple example.

C 代码:

// declare a pointer to a Fraction
struct Fraction *frac;

...

// reference an 'instance' variable
int n = (*frac).numerator;     // these two expressions
int n = frac->numerator;       // are equivalent

Objective-C 代码:

// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];

...

// reference an instance variable
int n = frac.numerator;        // why isn't this (*frac).numerator or frac->numerator??

那么,看到 frac 在两个程序中是如何相同的(即它是一个指向 Fraction 对象或结构的指针),为什么它们在访问属性时使用不同的语法?特别是,在 C 中,numerator 属性通过 frac->numerator 访问,但在 Objective-C 中,它使用点运算符访问,frac.numerator.既然 frac 在两个程序中都是一个指针,那么为什么这些表达式不同呢?谁能帮我澄清一下?

So, seeing how frac is the same in both programs (i.e. it is a pointer to a Fraction object or struct), why are they using different syntax when accessing properties? In particular, in C, the numerator property is accessed with frac->numerator, but with Objective-C, it is accessed using the dot operator, with frac.numerator. Since frac is a pointer in both programs, why are these expressions different? Can anyone help clarify this for me?

推荐答案

frac 实际上在两个程序中并不相同.

frac is actually not the same in both programs.

A C Fraction 是一个 struct,它是一个没有重载运算符的基本类型,并且只能在默认情况下真正地构造和析构.如果您在结构上定义函数或字段,则在 C 中访问这些属性的方法是使用点 (.) 运算符.当你使用 structs 时,Objective-C 会维护这个操作符.为方便起见,您可以使用箭头 (->) 运算符(您提到的两个等效表达式)执行取消引用和点操作.访问 structs 时,Objective-C 也保留了这一点.

A C Fraction is a struct, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C is with the dot (.) operator. Objective-C maintains this operator when you use structs. For convenience, you can perform a dereference-and-dot operation using the arrow (->) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing structs.

在您的示例中,Objective-C Fraction 可能(人们会假设)至少是 id 类型的指针,它只是一个类名和指针到引擎盖下那个类的实例.它也很可能是 NSObjectNSProxy 的子类.这些 Objective-C 类的特殊之处在于它们在一个 C 结构之上有一整层预定义的操作(如果你真的想深入研究它,那么你可以看看 Objective-C 运行时参考).同样需要注意的是,Objective-C 类始终是一个指针.

An Objective-C Fraction in your example, however, is probably (one would assume) a pointer of at least type id, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject or NSProxy. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.

最基本的操作之一是objc_msgSend.当我们对这些类型的对象进行操作时,Objective-C 编译器会将点(.)运算符或方括号语法([object method])解释为 >objc_msgSend 方法调用.有关此处实际发生的情况的更多详细信息,请参阅 本系列博文 由负责监督 Obj-C 运行时开发的 Apple 工程师 Bill Bumgarner 撰写.

One of the most basic operations is objc_msgSend. When we operate on these types of objects, the Objective-C compiler interprets a dot (.) operator or the square bracket syntax ([object method]) as an objc_msgSend method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.

箭头 (->) 操作符实际上不应该用于 Objective-C 对象.就像我说的,Objective-C 类实例是一个 C 结构,添加了额外的通信层,但是当您使用箭头时,该通信层实际上被绕过了.例如,如果您打开 Xcode 并输入 [UIApplication sharedApplication]-> 然后调出方法完成列表,您会看到:

The arrow (->) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]-> and then bring up the method completion list, you see this:

在这里你可以看到一堆我们通常用方括号语法访问的普通字段(比如[[UIApplication sharedApplication] delegate]).但是,这些特定项是 C 字段,用于存储它们各自的 Objective-C 属性的值.

Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]). These particular items, however, are the C fields that store the values of their respective Objective-C properties.

所以,你可以大致这样想:

So, you can roughly think of it like this:

C 对象上的点运算符

  1. (在运行时)返回字段的值

C 对象(指针)上的箭头运算符

  1. 解引用指针
  2. 字段的返回值

Objective-C 对象(指针)上的点运算符/方括号

  1. (在编译时)替换为对 objc_msgSend
  2. 的调用
  3. (在运行时)查找 Obj-C 类定义,如果出错则抛出异常
  4. 解引用指针
  5. 字段的返回值

Objective-C 对象(指针)上的箭头运算符

  1. (在运行时)解引用指针
  2. 字段的返回值

现在我在这里肯定是过于简单化了,但总而言之:箭头运算符在两种情况下似乎做的事情基本相同,但点运算符在 Objective-C 中具有额外/不同的含义.

Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.

这篇关于点(“.")运算符和箭头(“->")运算符在 C 与 Objective-C 中的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆