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!
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]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With