In this statement
printf("sizeof func = %zu\n", sizeof(func()));
there is outputted the size of the expression (that is not evaluated) func(). As the return type of the function is char then the expression func() has the type char and sizeof( char ) is equal to 1.
From the C Standard (6.5.3.4 The sizeof and alignof operators)
4 When sizeof is applied to an operand that has type char, unsigned
char, or signed char, (or a qualified version thereof) the result is
1....
In this statement
printf("sizeof func = %zu\n", sizeof(&func()));
there is an attempt to apply the unary operator & to a temporary object that is evaluated as the expression func(). You may not apply the operator to a temporary object.
From the C Standard (6.5.3.2 Address and indirection operators)
1 The operand of the unary & operator shall be either a function
designator, the result of a [] or unary * operator, or an lvalue
that designates an object that is not a bit-field and is not declared
with the register storage-class specifier.
for comparison consider the following program
#include <stdio.h>
char * func()
{
static char i = 0;
printf("sizeof func = %zu\n", sizeof(&*func()));
return &i;
}
int main(void)
{
func();
}
In this program the function returns pointer to the lvalue i with the static storage duration. So applying the unary operator * you will get the lvalue. So you may apply the operator & in this case.
The program output will be
sizeof func = 8
In this statement
printf("sizeof func = %zu\n", sizeof(&func));
there is evaluated the operator sizeof for a function pointer of the type char ( * )( void ). Again according to the quote from the C Standard the operator & may be applied to a function designator.
Take into account that the function definition shall look like
char func( void )
^^^^
{
printf("sizeof func = %zu\n", sizeof(func())); //Ok. Output : 1
return 0;
}