2010-05-04 2 views
3

Le 2ème argument du prototype getnameinfo demande un type socklen_t mais sizeof utilise size_t. Alors, comment puis-je obtenir socklen_t?getnameinfo spécifie 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); 

Exemple:

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); 

Cela donnera erreur compilateur:

socklen_t VAR; 
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0); 
+0

est 'sizeof' par lui-même causer un problème? –

+1

Obtenez-vous une erreur de compilation? –

+0

Pas de problème ou d'erreur de compilation mais je suppose que si getnameinfo demande socklen_t je ne devrais pas passer size_t ... –

Répondre

8

size_tis defined comme un type entier non signé; C99 garantit qu'il s'agit d'au moins 16 bits.

socklen_tis defined en tant que type intégral d'au moins 32 bits. (Edit: Ce n'est pas nécessairement non signé, bien que dans la pratique une longueur négative serait dénuée de sens.)

Il n'y a donc aucun problème avec le passage d'un paramètre size_t et de laisser le compilateur jeté implicitement à socklen_t, et je dirais que ce rend votre code plus clair pour laisser la conversion implicite se produire au lieu d'ajouter des moulages pédants.

Votre dernier exemple

socklen_t VAR; 
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0); 

donne une erreur de compilation parce que vous passez un pointeur à un socken_t au lieu d'un socklen_t.

+1

Plus précisément, la valeur retournée par 'sizeof' pour toute structure de type' sockaddr' sera toujours dans un type 'socklen_t', donc la conversion est sûre. – caf

0

(Ceci est plutôt une réponse à this IMHO falsely duplicate-tagged question qui essaie d'aller au fond de l » existence socklen_t.)

Comme d'autres l'ont souligné, il peut être considéré comme l'size_t équivalent de l'API Sockets POSIX représente la longueur de diverses structures de données en octets. Il est le plus notable dans les bind(), listen(), connect() fonctions où il dénote la longueur des différentes implémentations de struct sockaddr mais il n'est pas limité à cela.

Le POSIX specification explique comment il est devenu en fait être et est très instructif à mon humble avis:

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 .

Questions connexes