为什么某些 C 程序使用箭头运算符来指向结构的一部分而不是直接引用?
Why do certain C programs use an arrow operator to point to parts of a structure instead of directly referencing?
我正在开发一个 winsock2 程序,MSDN 上的一行代码引起了我的注意:
ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
为什么使用指针来引用结构而不是直接用点运算符引用结构?
编辑:查看此处的代码:Creating a Socket for the Client
在C/C++中,->
运算符用于访问指针指向的对象的属性和函数(即myClass->propOne
)。请记住,指针只是对内存的引用,您可以看到它不会有 propOne
,因为它只是一个内存位置。 ->
运算符表示您要访问位于 myClass
指向的内存中的对象的 propOne
。
您也可以通过使用 *
运算符取消引用指针来访问对象,然后使用 .
运算符访问道具(即 (*myClass).propOne
)来实现这一点.
它们都有效,但 ->
更简洁一些,并且可以减少编码错误。
解决 为什么 问题,使用指针的原因有很多。有时您想传递一个值或一个结构,但又不想复制它。有时您可能希望不止一件事能够轻松访问相同的结构。有时它只是更容易和更清洁。
.
运算符用于在对
进行操作时访问对象的成员
对象直接:
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
是指针的原因是代码使用了 getaddrinfo()
, which returns a dynamically allocated linked-list of addrinfo
结构,其中 ptr
是指向列表中特定项目的指针。
MSDN 示例仅访问列表中的第一项,但习惯上循环遍历整个列表,因为 getaddrinfo()
可以 return 多个地址。您需要使用指针循环遍历列表,例如:
#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.
我正在开发一个 winsock2 程序,MSDN 上的一行代码引起了我的注意:
ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
为什么使用指针来引用结构而不是直接用点运算符引用结构?
编辑:查看此处的代码:Creating a Socket for the Client
在C/C++中,->
运算符用于访问指针指向的对象的属性和函数(即myClass->propOne
)。请记住,指针只是对内存的引用,您可以看到它不会有 propOne
,因为它只是一个内存位置。 ->
运算符表示您要访问位于 myClass
指向的内存中的对象的 propOne
。
您也可以通过使用 *
运算符取消引用指针来访问对象,然后使用 .
运算符访问道具(即 (*myClass).propOne
)来实现这一点.
它们都有效,但 ->
更简洁一些,并且可以减少编码错误。
解决 为什么 问题,使用指针的原因有很多。有时您想传递一个值或一个结构,但又不想复制它。有时您可能希望不止一件事能够轻松访问相同的结构。有时它只是更容易和更清洁。
.
运算符用于在对
对象直接:
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
是指针的原因是代码使用了 getaddrinfo()
, which returns a dynamically allocated linked-list of addrinfo
结构,其中 ptr
是指向列表中特定项目的指针。
MSDN 示例仅访问列表中的第一项,但习惯上循环遍历整个列表,因为 getaddrinfo()
可以 return 多个地址。您需要使用指针循环遍历列表,例如:
#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.