1

在 C 中做与在 Java/C# 中->相同的事情吗?.

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

在我看来,它d_name在里面dir,它作为里面的一个项目被访问dir

DIR *d;
struct dirent *dir;
d = opendir("."); // get current directory
if (d)
{
    while ((dir = readdir(d)) != NULL)
    {
    // whilst item exists
    printf("%s\n", dir -> d_name);
    }
closedir(d);
}

如果不是这种情况,那么我错过了一些东西,如果可能的话,我想要一个简单的解释。

4

3 回答 3

4

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

于 2013-11-02T04:18:32.813 回答
1

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

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

让我们创建一个结构:

struct point_i {
    int x; 
    int y; 
};

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

然后使用结构:

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 语言的主要部分。

于 2013-11-02T04:52:15.977 回答
0

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

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

C# 中的结构的行为更像 C 中的结构。结构字段访问使用与.类字段访问相同的标记,但如果sS带有 field类型的结构f,则s.f在 C# 中就像s.f在 C 中一样。通过传递“byref”来调用实例方法到对象实例,这样s.im(whatever)就相当于S_im(&s, whatever);. 请注意,对结构类型变量的操作将对变量本身进行操作,这与对类类型变量的操作(与 C 的->标记一样)将在变量持有引用的某些东西上执行不同。

PS——我不喜欢使用 C#.而不是->类字段访问或通过传递包含在变量中的对象引用来调用类成员函数的决定。我宁愿看到foo.whatever一致地引用或修改foo自身,并foo->whatever一致地引用或修改一个foo拥有引用的事物。即使使用类对象,也可以实现非虚拟方法以将 byref 传递给变量,这样someString.Append(x);就可以等效于String_Append(ref x);并且可以更改变量someString所持有的内容(例如,使其指向 的不同实例String)。不过现在为时已晚。

于 2013-11-03T20:24:07.770 回答