为什么某些C程序使用箭头操作符指向结构的某些部分而不是直接引用?

为什么某些C程序使用箭头操作符指向结构的某些部分而不是直接引用?,c,pointers,structure,winsock2,C,Pointers,Structure,Winsock2,我当时正在开发一个winsock2程序,MSDN上的一行代码吸引了我的眼球: ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); 为什么指针用于引用结构,而不是使用点运算符直接引用结构 编辑:请参见此处的代码:在C/C++中,->操作符用于访问指针指向的对象的道具和函数(即myClass->propOne)。请记住,指针只是对内存的引用,您可以看到它不会有propOne,因为它只是

我当时正在开发一个winsock2程序,MSDN上的一行代码吸引了我的眼球:

ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
为什么指针用于引用结构,而不是使用点运算符直接引用结构


编辑:请参见此处的代码:

在C/C++中,
->
操作符用于访问指针指向的对象的道具和函数(即
myClass->propOne
)。请记住,指针只是对内存的引用,您可以看到它不会有
propOne
,因为它只是一个内存位置。
->
操作符表示要访问
myClass
指向的内存中对象的
propOne

您还可以通过使用
*
操作符取消对指针的引用来访问对象,然后使用
操作符访问该属性(即
(*myClass).propOne

它们都是有效的,但是
->
稍微干净一点,可以减少编码错误


在回答为什么的问题时,有很多理由使用指针。有时,您希望传递值或结构,但不希望复制它。有时,您可能希望不止一件事情能够轻松访问同一个结构。有时更简单、更干净。

在C/C++中,
->
操作符用于访问指针指向的对象的道具和函数(即
myClass->propOne
)。请记住,指针只是对内存的引用,您可以看到它不会有
propOne
,因为它只是一个内存位置。
->
操作符表示要访问
myClass
指向的内存中对象的
propOne

您还可以通过使用
*
操作符取消对指针的引用来访问对象,然后使用
操作符访问该属性(即
(*myClass).propOne

它们都是有效的,但是
->
稍微干净一点,可以减少编码错误


在回答为什么的问题时,有很多理由使用指针。有时,您希望传递值或结构,但不希望复制它。有时,您可能希望不止一件事情能够轻松访问同一个结构。有时它更简单、更干净。

当您对对象进行操作时,
操作符用于访问对象的成员

  • 直接将对象删除

    Type obj;
    obj.member
    
    Type obj;
    Type &ref = obj;
    ref.member
    
  • 对对象的引用

    Type obj;
    obj.member
    
    Type obj;
    Type &ref = obj;
    ref.member
    
  • ->
    操作符用于在操作对象的指针时访问对象的成员,而不是:

    Type obj;
    Type *ptr = &obj;
    ptr->member
    
    ->
    运算符只是将
    *
    运算符一起使用的一种更简洁的方法:

    Type obj;
    Type *ptr = &obj;
    (*ptr).member
    
    在这种情况下,由于
    ptr
    是指针,因此可以使用
    ->
    *。
    访问其成员

    在链接示例中,之所以
    ptr
    是指针,是因为代码正在使用,它返回一个动态分配的结构链接列表,其中
    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;
    }
    

    运算符用于在上操作时访问对象的成员

  • 直接将对象删除

    Type obj;
    obj.member
    
    Type obj;
    Type &ref = obj;
    ref.member
    
  • 对对象的引用

    Type obj;
    obj.member
    
    Type obj;
    Type &ref = obj;
    ref.member
    
  • ->
    操作符用于在操作对象的指针时访问对象的成员,而不是:

    Type obj;
    Type *ptr = &obj;
    ptr->member
    
    ->
    运算符只是将
    *
    运算符一起使用的一种更简洁的方法:

    Type obj;
    Type *ptr = &obj;
    (*ptr).member
    
    在这种情况下,由于
    ptr
    是指针,因此可以使用
    ->
    *。
    访问其成员

    在链接示例中,之所以
    ptr
    是指针,是因为代码正在使用,它返回一个动态分配的结构链接列表,其中
    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;
    }
    
    函数的第一个操作数。操作员应具有合格的或合格的 非限定结构或并集类型,第二个操作数应为 那种类型的成员

    ->运算符的第一个操作数应具有类型“”指针指向 合格或不合格结构“”或“”指向合格或不合格结构的指针 非限定并集“”,第二个操作数应命名 类型指向

    函数的第一个操作数。操作员应具有合格的或合格的 非限定结构或并集类型,第二个操作数应为 那种类型的成员

    ->运算符的第一个操作数应具有类型“”指针指向 合格或不合格结构“”或“”指向合格或不合格结构的指针 非限定并集“”,第二个操作数应命名 类型指向


    因为
    ptr
    是一个指针,如果您想知道
    ptr
    为什么是指针,您可以发布
    ptr
    的所有用法吗?换句话说,要访问
    p
    指向的结构的成员,您可以使用
    箭头
    操作符(例如
    p->member
    )。要访问
    struct p
    本身的成员,请使用
    dot
    ope