Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing struct element straight from function call in C

Tags:

c

gcc

struct

c99

c11

I don't fully understand if it's normal to get struct element straight from function call which returns struct (or pointer to struct) like in the following lines of code:

function().num
ptr_function(&var)->num


Below is code example I wrote which compiles and runs without any issues on my system.

#include <string.h>
#include <stdio.h>

#define LEN 32

typedef struct
{
  int     num;
  char    str[LEN];
} myType;


myType function( void )
{
  myType var;

  var.num = 10;
  strncpy( var.str, "Hello!", LEN );

  return var;
}

myType* ptr_function( myType* var )
{
  var->num = 20;
  strncpy( var->str, "Hello ptr!", LEN );

  return var;
}

int main()
{
  /* 1st example */
  printf( "%d %s\n", function().num, function().str );

  /* 2nd example */
  myType var;
  printf( "%d %s\n", ptr_function(&var)->num, ptr_function(&var)->str );

  return 0;
}

And it returns the following:

10 Hello!
20 Hello ptr!

So my question is: Are there any issues or undefined behaviour which will arise from doing the following in c99 or c11?

function().num
ptr_function(&var)->num
like image 949
antgleb Avatar asked Apr 07 '26 15:04

antgleb


1 Answers

Your example is technically correct and safe.

Do note that function() or ptr_function(&var) gets called twice. For some functions, that might not be desirable! And if you had different function calls such as outer(function1().value, function2().value), the order of the two function calls is not specified, so that could cause nasty surprises if they have interacting side effects.

Another possible catch to the pointer version of the pattern: If a function returns a pointer to allocated memory and expects the caller to free it, immediately using the return value result means the caller isn't keeping that pointer value and can't actually free it later.

[For a case like that, the code could still do:

someType *ptr;
outer_func((ptr = allocating_func())->field);
// ...
free(ptr);

but this is getting pretty strange and difficult to read. And since you need to declare ptr anyway, why not initialize it on the same line?]

This isn't an issue with the given example since the pointer actually points at var in main, so it doesn't need to be freed and is still valid when the -> operator is evaluated.

like image 76
aschepler Avatar answered Apr 10 '26 10:04

aschepler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!