-1

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?

funcs
  • 43
  • 6
  • `is this acceptable in C?` Does it compile? then it is technically acceptable. – Marcin Orlowski Dec 01 '17 at 22:22
  • 1
    @MarcinOrlowski Acceptability goes beyond the purview of compilation. ie. SHOULD it be done or not. – funcs Dec 01 '17 at 22:24
  • compiler understands, then it is technically acceptable. if your i.e. manager does not allow that but I.e. I do not give a damn on what he thinks, then it is acceptable or is it not? :) – Marcin Orlowski Dec 01 '17 at 22:27
  • 2
    @MarcinOrlowski -- plenty of code with undefined behavior will compile – ad absurdum Dec 02 '17 at 00:05
  • "*Pointer passed by value with cast*" there is no cast in the code shown. – alk Dec 02 '17 at 07:23
  • @alk Updated the title and tags to "compund literal". I was not familiar with this term before and believed it to be a cast. Sorry about the confusion. Thanks to John for the information. – funcs Dec 08 '17 at 16:11

2 Answers2

5

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.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • This is this information I was looking for. I was not familiar with term compound literal which made searching difficult. I was concerned whether there may be an issue passing it as an argument, but now I see it is valid. Thank you for the help. – funcs Dec 08 '17 at 16:03
  • 1
    Unfortunately, the Standard defines the lifetime of compound literals as extending only until the end of the nearest enclosing block--a lifetime which is will almost always either be longer than needed (limiting lifetime to the enclosing expression--as with arrays within return values of structure type--would usually be sufficient) or insufficient (in many cases where expression-based lifetime isn't adequate, the lifetime would need to extend further out than the nearest enclosing block). Present compilers seem to sensibly extend the lifetime, but I don't know if that will remain true. – supercat Dec 15 '17 at 21:26
-1

No need to guess, what you are doing with { 6, "second test"} is called struct initialization, and the way it worked until C99 is the compiler would assign values to the struct members in the order they were declared. So 6 is assigned to size and "second test" is assigned to str. (Since C99 you can indicate which member the value is assigned to with { .size = 6, .str = "second test" }.)

You then take the address of the created structure with & and pass that into your function.

mnistic
  • 10,866
  • 2
  • 19
  • 33
  • Thank you. I take it the second test is completely valid then. I was hearing concerns regarding the lack of a name for the pointer. I am familiar with the struct initialization part, it was the pointer without a variable that was causing worry. – funcs Dec 01 '17 at 22:37
  • Well, it is pointless because you can't use the struct for anything else, but it's not dangerous. – mnistic Dec 01 '17 at 22:39
  • No, no struct initialization *per se* there. That can take place only in the context of a declaration of a struct, of which there is none, and it would be recognizable by the `=` introducing it. – John Bollinger Dec 01 '17 at 22:40
  • I don't see any & in the second use? I believe that is what the question is about. – SoronelHaetir Dec 01 '17 at 22:41
  • @JohnBollinger Where do you get that from? Take a look at the link I provided, nested initialization. Nested structs are initialized without being "declared" with a "=" – mnistic Dec 01 '17 at 22:43
  • @JohnBollinger Dense, huh? You probably had a point, but it was kinda hard to read past the insult, so deserves a flag. – mnistic Dec 01 '17 at 23:11
  • 1
    No need to guess, perhaps, but this: `(MY_STRUCT) { 6, "second test"}` is a [compound literal](http://port70.net/~nsz/c/c11/n1570.html#6.5.2.5). Calling this a "`struct` initialization" is as misleading as calling this `"string literal"` an "array initialization". – ad absurdum Dec 02 '17 at 02:10
  • "the way it worked until C99": compound literals were not introduced in the Standard until C99. – ad absurdum Dec 02 '17 at 02:22
  • I apologize for giving offense, @mnistic. I took you to indeed be doing exactly as I said: *intentionally* putting on an act of misconstruing my words or being excessively nitpicky about them. – John Bollinger Dec 03 '17 at 18:15