简体   繁体   中英

Is x -> y the same in c as x.y in c#/java?

Is -> doing the same thing in C as . in Java/C#?

In Java/C# you access items inside a struct via the . operator.

It seems to me that d_name is inside dir and its being accessed as an item inside 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);
}

If this is not the case then I am missing something and I would like a simple explanation if possible.

In a vague sense, yes. Java does not have pointers, nor the concept of objects being passed by value; in essence, all objects are stored and passed by reference and the associated memory is freed by the garbage collector when unused.

Keep in mind the difference between an struct, and a pointer to an struct.

Let's assume a 32 bit compiler.

Let's create an struct:

struct point_i {
    int x; 
    int y; 
};

This struct has two int members. Each integer is four bytes in size so the struct size in total is eight bytes.

Then use the struct:

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

When you do this, the compiler knows where my_point is located and its size and it also knows where the member y is with respect to the struct. So it compiles (very roughly) to something like:

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.

On the other hand, when you have a pointer:

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.

And since the compiler has no idea what address you are going to put in that pointer it has to generate code that is a bit different.

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.

Notice that this is a very simplified view of the world. The compiler/linker and the operating system resolve memory addresses on your programs. But it should clarify what's going on behind the courtains. Pointer dereferencing is a major part of C.

Variables of class type in both .NET and Java hold references, whose behavior is similar to that of a malloc'ed pointer in C, except that C allows arithmetic and conversions between pointers and integers, whereas references allow no such arithmetic nor conversions. If o holds a reference to an object of class C with a field f , of in C# or Java is roughly equivalent to o->f in C.

Instance methods take an implied parameter, which is guaranteed to hold a reference to an instance of the appropriate type. If im is a non-virtual method of o , then o.im(whatever) is equivalent to C_im(o, whatever); . If vm is a virtual member, the system will define an internal method which returns the address of the implementation applicable to a given instance. Thus, o.vm(whatever) is equivalent to C_get_vm(o)(o, whatever);

Structures in C# behave more like structures in C. Structure field access uses the same . token as class field access, but if s is a structure of type S with field f , then sf in C# is like sf in C. Instance methods are called by passing a "byref" to the object instance, such that s.im(whatever) would be equivalent to S_im(&s, whatever); . Note that operations on a structure-type variable will operate on the variable itself, unlike operations on a class-type variable which (as with C's -> token) will be performed upon something to which the variable holds a reference.

PS--I dislike the decision to have C# use . rather than -> for class field access or for the invocation of class member functions by passing the object reference contained in a variable. I would rather have seen foo.whatever consistently refer to or modify foo itself, and foo->whatever consistently refer to or modify a thing to which foo holds a reference. Even with class objects, non-virtual methods could have been implemented to pass a byref to the variable, such that eg someString.Append(x); would have been equivalent to String_Append(ref x); and could change what the variable someString holds (eg making it point to a different instance of String ). Too late now, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM