为什么某些C程序使用箭头操作符指向结构的某些部分而不是直接引用?
我当时正在开发一个winsock2程序,MSDN上的一行代码吸引了我的眼球:为什么某些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,因为它只是
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