3

What I don't understand is the **res double pointer, in the man page it states:

The hints argument points to an addrinfo structure that specifies criteria for selecting the socket address structures returned in the list pointed to by res.

I see that *hints is a pointer to the addrinfo struct but how is **res returning the socket address structures?

Specification:

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);


struct addrinfo {
    int              ai_flags;
    int              ai_family;
    int              ai_socktype;
    int              ai_protocol;
    socklen_t        ai_addrlen;
    struct sockaddr *ai_addr;
    char            *ai_canonname;
    struct addrinfo *ai_next;
};
Jordan Davis
  • 1,485
  • 7
  • 21
  • 40
  • 1
    Have a look at the documentation, down at the very end of the is page http://man7.org/linux/man-pages/man3/getaddrinfo.3.html - dare to overcome TL;DR – alk Oct 01 '15 at 19:35

2 Answers2

3

The usage of a pointer to pointer is a common pattern where the function uses an "out" parameter to return the address of allocated memory. This is done so that the caller doesn't have to preallocate, sometimes an unknown size.

The typical usage of this is via the address operator (&) where you use a pointer type like this:

struct addrinfo *result;
getaddrinfo("foo", "baz", NULL, &result);

Then, result, which was an uninitialized variable is pointing to a real memory address, and later in the code it is expected it will be freed by the caller:

freeaddrinfo(result);
Amit
  • 45,440
  • 9
  • 78
  • 110
  • C does not have references, and the unary `&` operator is not conventionally called the "reference" operator in C context. Indeed, even in C++, I don't think the use of `&` to mark a reference type qualifies as an operation. The standard refers to unary `&` as the "address" operator, and elsewhere I frequently see that spelled "address-of". Otherwise, however, your explanation is good. – John Bollinger Oct 01 '15 at 19:49
  • @JohnBollinger A. You're right. B. I didn't even notice it was C and not C++ :-) – Amit Oct 01 '15 at 19:54
  • Same comment I posted below, why does it use `**` double not `*` single though, the `addrinfo` struct isn't a pointer so why do they use double in the spec. – Jordan Davis Oct 01 '15 at 20:10
  • @JordanDavis the variable is defined as a pointer (1 `*`) so that it points to a memory address with the values of the struct. The address operator grabs the address of the variable and passes it into the function so that it (`getaddrinfo`) can "mutate" the variable, and set the address it points to. It's much like you had a function: `void f(int *i) {};` and you used it with `int i; f(&i);`. – Amit Oct 01 '15 at 20:12
  • I understand that... again, why does it use `**` not `*` single – Jordan Davis Oct 01 '15 at 20:14
  • Again, so that it (the function, `getaddrinfo`) can allocate the memory for the `result` variable and return that address to be used (and later freed). Without the "double pointer", there'd be no way for it to return this address. – Amit Oct 01 '15 at 20:16
  • You can return an address using a `*` single pointer... so why can't it just be single like `*hint` is, what other pointer is `**result` pointing to.... – Jordan Davis Oct 01 '15 at 20:26
  • The function returns an address using a single pointer. It's just that the address is that of a pointer, not a "value" (as in, not an `int`, `float` and so on...). maybe this will help you see that better: `typedef struct addrinfo *paddrinfo; paddrinfo result; getaddrinfo("foo", "baz", NULL, &result);` and the function could have been defined as `getaddrinfo(const char *,..., *paddrinfo);` "Just one pointer". Regarding `*hint`, notice that this is an input parameter, not an output parameter, and it's unmodified by the function. – Amit Oct 01 '15 at 20:31
2

res is a pointer to the place where you want the results (which are themselves in the form of a pointer) stored. Thus you do something like:

struct addrinfo hints = { .ai_socktype = SOCK_STREAM };
struct addrinfo *ai;
int err_code = getaddrinfo(hostname, service, &hints, &ai));

Afterwards, if there was no error, ai has been updated to point at your results (the first element of a linked list of addrinfo structures).

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Why `**` double, even in your example your using `*` single and even in man page under the "client program" http://man7.org/linux/man-pages/man3/getaddrinfo.3.html it uses `struct addrinfo *result, *rp;` which is single. I mean the `struct addrinfo` isn't a pointer so why would I declare `**` double, you know. – Jordan Davis Oct 01 '15 at 19:57
  • @JordanDavis: The *res* argument is a pointer to a place to store a result. The result itself has pointer type. Thus the argument is a pointer to a pointer. This does not mean the result object (`ai` in my example code) should be a double-pointer type. Rather, you pass *the address of it*, `&ai`, whose type is "pointer to the type of `ai`" and thus *pointer to pointer to `struct addrinfo`*. – R.. GitHub STOP HELPING ICE Oct 01 '15 at 20:31