Search code examples
cpointerscompound-literals

Compound literal pointer passed as argument in C


Is passing a cast pointer by value valid in C? If not why is this working?

#include <stdio.h>

typedef struct 
{
    int   size;
    char* str;

} MY_STRUCT;

void print_my_struct_prt(MY_STRUCT* mstrct)
{
    printf("%s%d%s%s\n", "size: ", mstrct->size, " content: ", mstrct->str);
}

int main()
{
    MY_STRUCT my_ptr_strct;
    my_ptr_strct.size = 3;
    my_ptr_strct.str = "first test";
    print_my_struct_prt(&my_ptr_strct);

    print_my_struct_prt(&(MY_STRUCT) { 6, "second test"});

    return 0;
}

output:

size: 3 content: first test
size: 6 content: second test

In the first test a stuct is created, the values are set, and the address is passed to print_my_struct_prt().

In the second test I can only guess the values 6 and "second test" are stored in memory and the address to the location in memory is passed to print_my_struct_prt(). Is this correct?

Aside from obvious readability issues, is this acceptable in C?


Solution

  • Is passing a cast pointer by value valid in C? If not why is this working?

    C has only pass by value. When you pass a pointer, you pass it by value. There is nothing inherently wrong with passing a pointer value obtained via a cast.

    But I don't think that's what you mean to ask. Judging from the code, I think you're concerned about passing a pointer to the result of a cast, as opposed to passing the result of casting a pointer. In that case, passing in general and pass-by-value in particular have nothing to do with it. The result of a cast expression is not an lvalue, so you cannot take its address in the first place. You cannot obtain a pointer to the result of a cast.

    On the third hand, the code you've presented demonstrates something yet again different. Although this construct ...

    (MY_STRUCT) { 6, "second test"}
    

    ... resembles a cast expression, it is in fact a compound literal of type MY_STRUCT. Unlike the results of casts, compound literals are lvalues, so you can obtain their addresses. Having done so, you can pass the resulting pointer to a function or otherwise do whatever other thing you want that is permitted by its type.