Given:
int func(int x, int y) { /* ... */ }
the expression func is of function type. Specifically, it's of type int(int, int), which is C's syntax for the type "function with two int parameters returning int. (You won't often see that particular syntax, since it's not common to refer to function types directly.)
In most contexts, an expression of function type is implicitly converted to a pointer to the function; in this case, the pointer is of type int(*)(int, int).
The contexts in which this implicit conversion does not occur are:
When the expression is the operand of unary &; in that case, &func yields the address of the function (just as func by itself usually does); and
When the expression is the operand of sizeof. Without this exception, sizeof func would yield the size of a function pointer. Instead, it's a constraint violation, requiring a diagnostic from the compiler.
(A side note: This conversion does happen when the function name is used in a function call. The () "operator" (the standard doesn't call it that) requires a prefix of pointer-to-function type.)
gcc happens to have a non-standard extension; it permits pointer arithmetic on function pointers and on type void*, acting like pointer arithmetic on char* pointers (i.e., it operates in units of bytes). Unfortunately, IMHO, gcc did this via a kludge, setting the size of function types and of type void to 1. That's why you get sizeof func == 1; if you enable one of the standard conforming modes (e.g., gcc -std=c99 -pedantic), you'll get a warning.
Incidentally, don't use %d to print the result of sizeof. sizeof yields a result of type size_t. If your implementation supports it (C99 or later), use %zu; if not, you need to use a cast to explicitly convert the size_t value to something that you can print. For example:
printf("%lu\n", (unsigned long)sizeof &func);