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.