2013-11-02 25 views
1

->在C中執行的操作與.在Java/C#中執行的操作相同嗎?是否x - > y在c中與x.y在c#/ java中相同?

在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); 
} 

如果不是這種情況,那麼我失去了一些東西,如果可能,我想一個簡單的解釋。

+1

我不想說它是相同的,但它在類似的意義上是存在*隱式*「引用」發生。 – user2864740

回答

4

從含義上講,是的。 Java沒有指針,也沒有按值傳遞對象的概念;本質上,所有對象都是按引用存儲和傳遞的,並且在未使用時,關聯的內存由垃圾回收器釋放。

+0

謝謝,所以它真的很簡單,'d_name'在'dir'結構中。 – Joseph

+0

關閉,但'dir'是一個指向一個結構的指針,該結構在提取'd_name'成員之前被解引用(後面)。 'dir-> d_name'等價於'(* dir).d_name'。 –

+0

謝謝,我需要做更多的* dereferencing *指針才能真正理解。我仍然不完全明白* dereference *的含義。但是你的回答已經清除了上述代碼中發生的事情,所以非常感謝你! – Joseph

1

請記住struct和指向結構體的指針之間的區別。

讓我們假設一個32位編譯器。

讓我們創建一個結構:

struct point_i { 
    int x; 
    int y; 
}; 

這個結構有兩個int成員。每個整數的大小是四個字節,所以結構大小總共爲八個字節。

然後用結構:

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. 

請注意,這是一個非常簡化的世界觀。編譯器/鏈接器和操作系統解析程序上的內存地址。但它應該澄清在courtain背後發生了什麼。指針取消引用是C的主要部分。

+0

_注意這是一個非常簡化的世界觀......真的嗎? :) – ryyker

+0

好吧,也許不是*那麼簡單:) –

0

.NET和Java中的類型變量保持引用,其行爲與C中的malloc'ed指針的行爲類似,不同之處在於C允許指針之間的算術和轉換和整數,而引用不允許這樣的算術和轉換。如果o持有C#與現場f的引用類C的對象,o.f或Java大致相當於o->f中C.

實例方法採取一個隱含的參數,這是保證用於保持參考實例的適當類型。如果imo的非虛擬方法,則o.im(whatever)相當於C_im(o, whatever);。如果vm是虛擬成員,則系統將定義一個內部方法,該方法返回適用於給定實例的實現的地址。因此,o.vm(whatever)相當於C_get_vm(o)(o, whatever);

結構在C#操作起來更象在C.結構字段訪問結構使用相同的.令牌作爲類字段訪問,但如果sS類型的與現場f的結構,然後s.f在C#與C中的s.f相似。通過將「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的不同實例)。雖然現在太晚了。

相關問題