简体   繁体   中英

Why do certain C programs use an arrow operator to point to parts of a structure instead of directly referencing?

I was working on a winsock2 program, and one line of code on MSDN caught my eye:

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

Why is a pointer used to reference the structure instead of directly referencing the structure with the dot operator?

EDIT: see the code here: Creating a Socket for the Client

In C/C++, the -> operator is used to access the props and functions of an object that a pointer is pointing at (ie. myClass->propOne ). Keeping in mind that a pointer is just a reference to memory, you can see that it would not have propOne since it is just a memory location. The -> operator says that you want to access propOne of the object located in the memory that myClass is pointing at.

You could also achieve this by dereferencing the pointer with the * operator to access the object, and then use the . operator to access the prop (ie. (*myClass).propOne ).

They are both valid, but the -> is a bit cleaner, and can lead to fewer coding errors.

Addressing the why question, there are a lot of reasons to use pointers. Sometimes you want to pass around a value or a structure but you do not want to copy it. Sometimes you may want more than one thing to be able to access the same structure easily. Sometimes it is just easier and cleaner.

The . operator is used to access members of an object when you are operating on

  1. the object directly :

     Type obj; obj.member 
  2. a reference to the object :

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

The -> operator is used to access members of an object when you are operating on a pointer to the object instead:

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

The -> operator is just a cleaner way of using the * and . operators together:

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

In this case, since ptr is a pointer, you can use either -> or *. to access its members.

In the linked example, the reason ptr is a pointer is because the code is using getaddrinfo() , which returns a dynamically allocated linked-list of addrinfo structures, where ptr is a pointer to a particular item in the list.

The MSDN example only accesses the first item in the list, but it is customary to loop through the entire list, as getaddrinfo() can return multiple addresses. You need to use a pointer to loop through the list, eg:

#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;
}
ISO/IEC 9899:TC3

6.5.2.3 Structure and union members

The first operand of the . operator shall have a qualified or unqualified structure or union type, and the second operand shall name a member of that type.

The first operand of the -> operator shall have type ''pointer to qualified or unqualified structure'' or ''pointer to qualified or unqualified union'', and the second operand shall name a member of the type pointed to.

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