Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does getaddrinfo() take the node, service and hints arguments as pointers? [duplicate]

int getaddrinfo(const char *node,     // e.g. "www.example.com" or IP
                const char *service,  // e.g. "http" or port number
                const struct addrinfo *hints,
                struct addrinfo **res);

I am trying to learn networking with C but I don't understand why the function takes the input parameters as pointers? I understand that hints is a struct and it should be passed by reference. But node and service are not structs.

I would expect the node and service parameters to be passed by value.

It seems that it is also related to "array-to pointer decay" but char node[] and char* node[] are not exactly the same thing!

like image 809
SMH_88 Avatar asked Nov 30 '25 10:11

SMH_88


1 Answers

It's unclear what you think could be used instead of a pointer.

We can't pass an array to a function. There's simply no mechanism for doing so. We can pass a pointer to an array, or more commonly a pointer to its first element, but not the array itself.

You may be confused by code like this

char str[] = "Hi";    // An array

puts( str );

It looks like an array is being passed as a parameter, but that call is equivalent to

char str[] = "Hi";    // An array

puts( &( str[0] ) );  // A pointer to its first element

A pointer is passed to the function.


As a side note, you can pass an array to a function if it's part of a struct.

#include <stdio.h>

#define MAX_NODE_NAME_SIZE 100

struct NodeName {
   char data[ MAX_NODE_NAME_SIZE ];
};

void f( struct NodeName node_name ) {
   printf( "%s\n", node_name.data );
}

int main( void ) {
   struct NodeName node_name = { "www.example.org" };

   f( node_name );
}

Unfortunately, you need to know the maximum size of the array and must always allocate one that size. And it's a crazy amount of work, code and CPU cycles for nothing. Using a pointer is much better.

#include <stdio.h>

void f( const char *node_name ) {
   printf( "%s\n", node_name );
}

int main( void ) {
   char node_name[] = "www.example.org";

   f( node_name );
}

Finally, C always passes by value. Changes to the parameters are never reflected in the caller. Don't confuse passing a pointer (by value or otherwise) with passing by reference.

#include <stdio.h>

void f( int i ) { i = 4; }

void g( int *p ) { p = NULL; }

int main( void ) {
   int i = 3;
   printf( "%d\n", i );         // 3
   f( i );
   printf( "%d\n", i );         // 3

   printf( "\n" );

   int *p = &i;
   printf( "%p\n", (void*)p );  // 0x7ffe3df36414
   g( p );
   printf( "%p\n", (void*)p );  // 0x7ffe3df36414
}

Compare this to the line-for-line equivalent program in Perl, which always passes by reference.

use v5.14;
use warnings;

sub f { $_[0] = 4; }

sub g { $_[0] = undef; }

{
   my $i = 3;
   say $i;               # 3
   f( $i );
   say $i;               # 4

   say "";

   my $p = \$i;
   say $p // "[undef]";  # SCALAR(0x5e81960a0c68)
   g( $p );
   say $p // "[undef]";  # [undef]
}
like image 109
ikegami Avatar answered Dec 02 '25 23:12

ikegami