我工作的一個Winsock2的方案,並在MSDN上一行代碼吸引了我的眼球:爲什麼某些C程序使用箭頭運算符來指向結構的某些部分而不是直接引用?
ConnectSocket=socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
爲什麼使用指針引用結構,而不是用點操作直接引用的結構?
編輯:在這裏看到的代碼:Creating a Socket for the Client
我工作的一個Winsock2的方案,並在MSDN上一行代碼吸引了我的眼球:爲什麼某些C程序使用箭頭運算符來指向結構的某些部分而不是直接引用?
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()
,它返回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;
}
ISO/IEC 9899:TC3
6.5.2.3 Structure and union members
的第一個操作數。運營商應具有合格的或不合格的結構或聯合類型,第二個操作數應將 命名爲該類型的成員。
的第一個操作數 - >運算符應有類型「」指針 合格或不合格的結構「」或「」指針合格或 不合格工會「」,和第二個操作數應命名 的成員類型指向。
因爲'ptr'是一個指針,如果你想知道爲什麼'ptr'是一個指針,你可以發佈'ptr'的所有用法嗎? –
換句話說,要訪問'p'指向的結構成員,可以使用'arrow'運算符(例如'p-> member')。爲了訪問'struct p'本身的成員,可以使用'dot'運算符(例如'p.member')。 –
你如何建議*當'ptr'是一個指針時直接*使用點運算符? – AnT