2016-10-15 29 views
0

我工作的一個Winsock2的方案,並在MSDN上一行代碼吸引了我的眼球:爲什麼某些C程序使用箭頭運算符來指向結構的某些部分而不是直接引用?

ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); 

爲什麼使用指針引用結構,而不是用點操作直接引用的結構?

編輯:在這裏看到的代碼:Creating a Socket for the Client

+0

因爲'ptr'是一個指針,如果你想知道爲什麼'ptr'是一個指針,你可以發佈'ptr'的所有用法嗎? –

+0

換句話說,要訪問'p'指向的結構成員,可以使用'arrow'運算符(例如'p-> member')。爲了訪問'struct p'本身的成員,可以使用'dot'運算符(例如'p.member')。 –

+0

你如何建議*當'ptr'是一個指針時直接*使用點運算符? – AnT

回答

2

在C/C++中,->操作者用來訪問對象的道具和函數的指針在(即myClass->propOne)指向。請記住,指針只是對內存的引用,你可以看到它不會有propOne,因爲它只是一個內存位置。 ->運算符說您想訪問位於myClass指向的內存中的對象的propOne

您也可以通過取消指針與*運算符訪問該對象,然後使用.運算符訪問該道具(即(*myClass).propOne)來實現此目的。

它們都是有效的,但->有點乾淨,並且可能導致更少的編碼錯誤。

尋址爲什麼問題,有很多原因使用指針。有時你想傳遞一個值或一個結構,但你不想複製它。有時你可能希望不止一件事情能夠輕鬆訪問同一結構。有時它更簡單,更清潔。

1

.運算符用於當你在

  1. 對象直接操作以訪問對象的成員:

    Type obj; 
    obj.member 
    
  2. 到對象的引用:

    Type obj; 
    Type &ref = obj; 
    ref.member 
    

->運算符用於訪問對象的成員,當你在指針操作對象代替:

Type obj; 
Type *ptr = &obj; 
ptr->member 

->運營商只是一個使用*的清潔方式.運營商一起,:

Type obj; 
Type *ptr = &obj; 
(*ptr).member 

在這種情況下,由於ptr是一個指針,可以使用->*.訪問其成員。

在鏈接例子,原因ptr是一個指針是因爲代碼是使用getaddrinfo(),它返回addrinfo結構中,當ptr是指向列表中的特定項目的一個動態分配的鏈表。

MSDN示例只訪問列表中的第一個項目,但它習慣於遍歷整個列表,因爲getaddrinfo()可以返回多個地址。您需要在列表中使用指針來循環,例如:

#define DEFAULT_PORT "27015" 

int main(int argc, char** argv) 
{ 
    SOCKET ConnectSocket = INVALID_SOCKET; 
    struct addrinfo *result = NULL, 
        *ptr = NULL, 
        hints; 
    int iResult; 
    WSADATA wsa; 

    iResult = WSAStartup(MAKEWORD(2, 0), &wsa); 
    if (iResult != 0) { 
     printf("WSAStartup failed: %d\n", iResult); 
     return 1; 
    } 

    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; // allows IPv4 and IPv6 addresses 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 

    // Resolve the server address and port 
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result); 
    if (iResult != 0) { 
     printf("getaddrinfo failed: %d\n", iResult); 
     WSACleanup(); 
     return 1; 
    } 

    // Attempt to connect to each address returned by 
    // the call to getaddrinfo until one succeeds 
    for(ptr = result; ptr != NULL; ptr = ptr->ai_next) 
    { 
     // Create a SOCKET for connecting to server 
     ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); 
     if (ConnectSocket == INVALID_SOCKET) { 
      printf("Error at socket(): %ld\n", WSAGetLastError()); 
      continue; 
     } 

     // connect to server 
     iResult = connect(ConnectSocket, ptr->ai_addr, ptr->ai_addrlen); 
     if (iResult == 0) { 
      printf("Connected!\n"); 
      break; 
     } 

     printf("Unable to connect: %ld\n", WSAGetLastError()); 

     // Destroy the SOCKET before trying the next address 
     closesocket(ConnectSocket); 
     ConnectSocket = INVALID_SOCKET; 
    } 

    freeaddrinfo(result); 

    if (ConnectSocket != INVALID_SOCKET) { 
     // use ConnectSocket as needed... 
     closesocket(ConnectSocket); 
    } 

    WSACleaup(); 
    return 0; 
} 
0
ISO/IEC 9899:TC3 

6.5.2.3 Structure and union members 

的第一個操作數。運營商應具有合格的或不合格的結構或聯合類型,第二個操作數應將 命名爲該類型的成員。

的第一個操作數 - >運算符應有類型「」指針 合格或不合格的結構「」或「」指針合格或 不合格工會「」,和第二個操作數應命名 的成員類型指向。

相關問題