The 2nd arg for the getnameinfo prototype asks for a socklen_t type but sizeof uses size_t. So how can I get socklen_t ?
Prototype:
int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
char *restrict node, socklen_t nodelen, char *restrict service,
socklen_t servicelen, int flags);
Example:
struct sockaddr_in SIN;
memset(&SIN, 0, sizeof(SIN)); // This should also be socklen_t ?
SIN.sin_family = AF_INET;
SIN.sin_addr.s_addr = inet_addr(IP);
SIN.sin_port = 0;
getnameinfo((struct sockaddr *)&SIN, sizeof(SIN) /* socklen_t */, BUFFER, NI_MAXHOST, NULL, 0, 0);
This will give compiler error:
socklen_t VAR;
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0);
size_t
is defined as an unsigned integral type; C99 guarantees that it is at least 16 bits.
socklen_t
is defined as an integral type of at least 32 bits. (Edit: It's not necessarily unsigned, although in practice a negative length would be meaningless.)
So there's no problem with passing a size_t
parameter and letting the compiler implicitly cast it to socklen_t
, and I would argue that it makes your code clearer to let the implicit conversion occur instead of adding pedantic casts.
Your final example
socklen_t VAR;
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0);
gives a compiler error because you're passing a pointer-to-a-socken_t instead of a socklen_t.
Your information are out of date, socklen_t is an integer type (not necesarily unsigned) of at least 32 bits (http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html).
(This is rather an answer to this IMHO falsely duplicate-tagged question that tries to get to the bottom of socklen_t
's existence.)
As others have pointed out it can be thought of as the size_t
equivalent of the POSIX Sockets API that represents the length of various data structures in bytes. It is most notable in the bind()
, listen()
, connect()
functions where it denotes the length of the various implementations of struct sockaddr
but it is not limited to that at all.
The POSIX specification actually explains how it became to be and is very instructive IMHO:
The type socklen_t
was invented to cover the range of implementations seen in the field. The intent of socklen_t
is to be the type for all lengths that are naturally bounded in size; that is, that they are the length of a buffer which cannot sensibly become of massive size: network addresses, host names, string representations of these, ancillary data, control messages, and socket options are examples. Truly boundless sizes are represented by size_t
as in read()
, write()
, and so on.
All socklen_t
types were originally (in BSD UNIX) of type int
. During the development of POSIX.1-2008, it was decided to change all buffer lengths to size_t
, which appears at face value to make sense. When dual mode 32/64-bit systems came along, this choice unnecessarily complicated system interfaces because size_t
(with long) was a different size under ILP32 and LP64 models. Reverting to int
would have happened except that some implementations had already shipped 64-bit-only interfaces. The compromise was a type which could be defined to be any size by the implementation: socklen_t
.