是x - >与c#/ java中的x.y相同?

时间:2013-11-02 04:16:11

标签: c struct

->在C中与{/ 1}中的{/ 1}}做同样的事情吗?

在Java / C#中,您可以通过.运算符访问结构中的项目。

在我看来,.位于d_name内,其作为dir内的项目进行访问

dir

如果情况并非如此,那么我错过了一些内容,如果可能的话,我想要一个简单的解释。

3 个答案:

答案 0 :(得分:4)

含糊不清,是的。 Java没有指针,也没有按值传递的对象的概念;本质上,所有对象都是通过引用存储和传递的,并且在未使用时,垃圾收集器会释放相关的内存。

答案 1 :(得分:1)

请记住struct和指向struct的指针之间的区别。

让我们假设一个32位编译器。

让我们创建一个结构:

struct point_i {
    int x; 
    int y; 
};

此结构有两个int成员。每个整数的大小为4个字节,因此结构大小总共为8个字节。

然后使用struct:

strut point_i my_point;        // 8 bytes allocated, lets assume that they  
                               // are located at address 0x10000000.
my_point.y = 10;              

执行此操作时,编译器会知道my_point的位置及其大小,并且还知道成员y相对于结构的位置。因此它(非常粗略地)编译为:

MOV [0x10000004], 10     ;; Notice that its 0x10000000 + 4. 
                         ;; The first four bytes are X so we skip them 
                         ;; to get to Y and put 10 in that memory address.

另一方面,当你有一个指针时:

strut point_i *another_point;       // 4 bytes allocated, the pointer size.
                                    // Let's assume in 0x20000000.

another_point = get_random_point(); // Get an address to some random point.

another_point->y = 10;              // You have to use -> to reference the member
                                    // because you are not dealing with an struct
                                    // anymore but a *pointer* to said struct.

由于编译器不知道你要在该指针中放入什么地址,因此它必须生成稍有不同的代码。

MOV EBX, [0x20000000]     ;; 0x20000000 has your pointer. So we fetch it.
MOV [EBX+4], 10           ;; Dereference the pointer and put 10 in Y. 
                          ;; You can see that we now have two memory references, 
                          ;; one to get the pointer and another to get where it
                          ;; points to. So it is a layer of indirection.

请注意,这是一个非常简化的世界观。编译器/链接器和操作系统解析程序上的内存地址。但它应该澄清这些背后发生的事情。指针解除引用是C的主要部分。

答案 2 :(得分:0)

.NET和Java中类类型的变量保存引用,其行为类似于C中malloc指定的行为,除了C允许指针和整数之间的算术和转换,而引用不允许这样的算法和转换。如果o包含对带有字段f的C类对象的引用,则C#或Java中的o.f大致相当于C中的o->f

实例方法采用隐含参数,该参数保证包含对相应类型的实例的引用。如果imo的非虚方法,则o.im(whatever)相当于C_im(o, whatever);。如果vm是虚拟成员,系统将定义一个内部方法,该方法返回适用于给定实例的实现的地址。因此,o.vm(whatever)相当于C_get_vm(o)(o, whatever);

C#中的结构更像C中的结构。结构字段访问使用与类字段访问相同的.标记,但如果s是带有字段{S的结构f {1}},然后C#中的s.f与C中的s.f类似。通过将“byref”传递给对象实例来调用实例方法,这样s.im(whatever)将等同于S_im(&s, whatever); {1}}。请注意,对结构类型变量的操作将对变量本身进行操作,不像对类型变量的操作(与C的->标记一样)将对变量保存引用的内容执行。 / p>

PS - 我不喜欢决定让C#使用.而不是->来进行类字段访问,或者通过传递变量中包含的对象引用来调用类成员函数。我宁愿看到foo.whatever始终引用或修改foo本身,而foo->whatever始终引用或修改foo拥有引用的内容。即使使用类对象,也可以实现非虚方法以将byref传递给变量,例如, someString.Append(x);等同于String_Append(ref x);,可以更改变量someString的含义(例如,使其指向String的不同实例)。但现在太迟了。