5

Why does the following code give:

#include<stdio.h>

int voo()
{
    printf ("Some Code");
    return 0;
}


int main() {
    printf ("%zu", sizeof voo);
    return 0;
}

The following output:

1
Brendan Long
  • 53,280
  • 21
  • 146
  • 188
Expert Novice
  • 1,943
  • 4
  • 22
  • 47

2 Answers2

9

The C language does not define sizeof for functions. The expression sizeof voo violates a constraint, and requires a diagnostic from any conforming C compiler.

gcc implements pointer arithmetic on function pointers as an extension. To support this, gcc arbitrarily assumes that the size of a function is 1, so that adding, say, 42 to the address of a function will give you an address 42 bytes beyond the function's address.

They did the same thing for void, so sizeof (void) yields 1, and pointer arithmetic on void* is permitted.

Both features are best avoided if you want to write portable code. Use -ansi -pedantic or -std=c99 -pedantic to get warnings for this kind of thing.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Would whoever downvoted this be kind enough to explain why? – Keith Thompson Aug 08 '11 at 21:37
  • Keith, there are some drive-by sociopaths at SO; don't count on an explanation from them. I gave you +1. – Jim Balter Aug 09 '11 at 00:06
  • @Jim: Thanks! But really, I'm more bothered by the possibility that someone might have had a legitimate criticism and didn't bother to share it. (I wonder how well a requirement to leave a comment when downvoting would go over. A question for meta, perhaps.) – Keith Thompson Aug 09 '11 at 00:34
  • @Keith Someone may have a legitimate criticism of your post, but it is not conceivable that anyone has a valid reason to *downvote* it. And I think that requirement would be a good idea, and in line with the FAQ. – Jim Balter Aug 09 '11 at 00:48
  • I've long been in favour of such a requirement (or alternatively, they can upvote an existing comment, presumably a criticism of the answer that they're agreeing with). – caf Aug 09 '11 at 02:45
  • @Jim: I think I've come up with a solution to the drive-by downvote problem: Not worrying about it. (It's been discussed at length on meta.) – Keith Thompson Aug 09 '11 at 14:48
3

The C99 Standard says:

6.3.2.1/4

Except when it is the operand of the sizeof operator 54) or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.

and in the 54) footnote, it says

Because this conversion does not occur, the operand of the sizeof operator remains a function designator and violates the constraint in 6.5.3.4.

The relevant passage out of 6.5.3.4 is

The sizeof operator shall not be applied to an expression that has function type or an incomplete type

From which we can conclude your program invoked Undefined Behaviour and no explanation can be given for the output.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • 3
    Yes, the program invokes undefined behavior (assuming it compiles at all, which it likely won't). That doesn't imply that "no explanation can be given for the output". See, for example, my explanation for the output. (It's true, and quite relevant, that the language standard gives no explanation for the output.) – Keith Thompson Aug 08 '11 at 20:48
  • Of course you can explain the output of UB if you know the compiler used to compile the code, its options, the Operating System, and the phase of the moon :) *The OP just hinted that he is using a C99 compiler, which rules out Microsoft Visual Studio...* – pmg Aug 08 '11 at 20:54
  • 2
    All I needed to know was the compiler, which I inferred from the program's output. – Keith Thompson Aug 08 '11 at 21:10
  • @Keith You are right. UB does not mean that no explanation can be given, or anything like that, and it's sad that a number of people make such silly claims. All it means is that the C standard puts no constraint on what conforming implementations may do. – Jim Balter Aug 09 '11 at 00:04
  • @Keith P.S. As you mention in your answer, since this is a constraint violation then the standard requires conforming implementations to issue a diagnostic. However, gcc without -pedantic is not a conforming implementation, so the C standard doesn't govern its behavior; what does govern it is the gcc documentation. It might be a good idea to have a *stdc* tag for language lawyering, and the plain *c* tag would only apply to questions where the implementation and whether it conforms to the standard isn't relevant. – Jim Balter Aug 09 '11 at 00:59
  • 1
    @Jim: This probably isn't right place for this kind of meta-discussion, but my own tendency is to discuss both, while making it clear which part of the answer relates to the standard language and which is implementation-specific. Even people writing non-portable code can benefit, IMHO, from knowing exactly what's non-portable about it. (BTW, there is a "language-lawyer" tag.) – Keith Thompson Aug 09 '11 at 23:54