90

When we check the size of a function using sizeof(), we always get 1 byte. What does this 1 byte signify?

Jarekczek
  • 7,456
  • 3
  • 46
  • 66
user1645461
  • 791
  • 5
  • 4

4 Answers4

80

It's a constraint violation, and your compiler should diagnose it. If it compiles it in spite of that, your program has undefined behaviour [thanks to @Steve Jessop for the clarification of the failure mode, and see @Michael Burr's answer for why some compilers allow this]: From C11, 6.5.3.4./1:

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

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 11
    That's a constraint, which means in a conforming compiler it's diagnosed. If the compiler compiles it anyway (having diagnosed it), then behavior is undefined. If the compiler doesn't diagnose it (which for example gcc doesn't without `-pedantic`), you have a non-conforming compiler and *every* program has undefined behavior. – Steve Jessop Sep 04 '12 at 09:46
  • @SteveJessop: This is really strange: If this were on the same level as a *syntax error*, as Michael Burr suggests, then how come the compiler is really reluctant to diagnose this? I have to say `-pedantic` to GCC to get it to speak up. – Kerrek SB Sep 04 '12 at 09:48
  • 1
    The behavior puts it in the same category as a GNU C extension, but I have no idea why anyone *wants* that behavior, so I don't know why the GNU authors went out of their way to add it. – Steve Jessop Sep 04 '12 at 09:49
  • 1
    @SteveJessop: Note that this is even with `-std=c11`, *not* `gnu11`. This is a really weird compiler extension. – Kerrek SB Sep 04 '12 at 09:50
  • 6
    Ooh! I bet it's to enable arithmetic on function pointers, the same way that `sizeof(void)` is 1 in GNU C. – Steve Jessop Sep 04 '12 at 09:52
  • @SteveJessop: Ah, yes, that explains why that extension would seem desirable. Good stuff. – Kerrek SB Sep 04 '12 at 09:56
  • 3
    Regarding `-std=c11`: someone should refer the `-std=c*` options to Advertising Standards. They don't enable conformance mode, they merely disable extensions that would prevent a well-formed program from compiling (such as `typeof` being a keyword, since a well-formed C program can use it as a variable name, but `gcc` by default would reject that). To additionally disable extensions that allow ill-formed programs to pass undiagnosed, you need `-pedantic` or `-pedantic-errors`. – Steve Jessop Sep 04 '12 at 09:58
  • 1
    Implementations, not compilers, are conforming or not conforming. gcc with -pedantic is a different implementation from gcc without -pedantic. – Jim Balter Sep 08 '12 at 01:57
56

This is not undefined behavior - the C language standard requires a diagnostic when using the sizeof operator with a function designator (a function name) since it's a constraint violation for the sizeof operator.

However, as an extension to the C language, GCC allows arithmetic on void pointers and function pointers, which is done by treating the size of a void or a function as 1. As a consequence, the sizeof operator will evaluate to 1 for void or a function with GCC. See http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith

You can get GCC to issue a warning when using sizeof with these operands by using the -pedantic or -Wpointer-arith options to GCC. Or make it an error with -Werror=pointer-arith.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Your logic is flawed. C requires diagnostic messages for some, but not all UB. You can't state that something has defined behavior just because there's a diagnostic. – MSalters Sep 04 '12 at 09:05
  • 4
    C requires a diagnostic for all constraint violations (5.1.1.3 Diagnostics in C99 or C11). A constraint (3.8 in C99/C11) is a "restriction, either syntactic or semantic, by which the exposition of language elements is to be interpreted", which seems to say that something that doesn't follow the constraints can't be interpreted. – Michael Burr Sep 04 '12 at 09:13
  • 3
    And to be clear - a constraint violation doesn't result in undefined behavior. It's an error, like a syntax error. For example, the standard says, "if a "shall" or "shall not" requirement that appears **outside of a constraint** is violated, the behavior is undefined". If a constraint violation would result in UB, why would the standard talk about only the "shalls" and "shall nots" that aren't in constraints here? – Michael Burr Sep 04 '12 at 09:27
  • Indeed. But again you can't invert that logic. You can't say that every diagnostic is a constraint violation. In fact, it's been observed that strictly speaking, a compiler may emit a "this line could be incorrect" diagnostic for _every_ line of code and nothing else. – MSalters Sep 04 '12 at 09:28
  • @MSalters: it's a constraint violation because it's the "Constraints" section of the `sizeof` operator's description that says `sizeof` cannot be applied to a function type. That's what makes this a constraint violation (and therefore an error that requires a diagnostic). – Michael Burr Sep 04 '12 at 09:32
  • Sure, not arguing that. But you state that it's **not** UB because the categories "Constraint Violation" and "UB" are orthogonal, because the former results in a diagnostic (and presumably the latter doesn't). That logic is flawed. UB can cause a diagnostic (anything can), therefore the categories are not orthogonal. – MSalters Sep 04 '12 at 09:37
  • @MichaelBurr: How come the OP *doesn't* get a diagnostic then? – Kerrek SB Sep 04 '12 at 09:41
  • 3
    I really didn't state much of anything about UB except that `sizeof` a function isn't UB (which I mentioned pretty much only because other answers stated it was UB). But perhaps I muddled that because of the way I structured the sentence. To be more clear. `sizeof` a function is not UB (as several answers have claimed). It is a constraint violation. As such, it requires a diagnostic. GCC permits it as an extension. – Michael Burr Sep 04 '12 at 09:50
  • 2
    @KerrekSB: the OP doesn't get a diagnostic because presumably they are using GCC, which permits this use as a C language extension. – Michael Burr Sep 04 '12 at 09:52
  • @MichaelBurr: OK, thanks. I've edited my answer to make it more accurate. – Kerrek SB Sep 04 '12 at 09:52
  • Requiring a diagnostic doesn't mean that the code must not compile, does it? A warning is a kind of diagnostic. After issuing the diagnostic, I'd say that the value of this is implementation-defined, just as the value of `sizeof(int)` is implementation-defined (the standard only defines the size of `char` -- other data types have minimum sizes, but not standard sizes). – Barmar Sep 04 '12 at 18:53
  • @Barmar: a diagnostic doesn't necessarily mean an error, but a constraint violation is on the order of a syntax error - see my first comment above. So if you don't get an error from the compiler on a constraint violation, that would be a similar situation to a compiler not giving an error on the following: `int x = "abc" << "123";` I suppose it's possible that you might find a compiler that will only issue a warning for that. – Michael Burr Sep 04 '12 at 19:16
  • But if the compiler has added a meaning for it as an extension (as GCC has in this case), it wouldn't make sense for it to generate a fatal error, but a warning might still be appropriate. – Barmar Sep 05 '12 at 20:40
  • Yes - if the compiler provides something useful/intended as an extension then it certainly wouldn't make sense to produce an error. The point I'm trying to get across is that this isn't undefined behavior. It's either an error (when following a bog-standard spec) or it acts according to some non-standard language extension (as in this case with GCC). But this doesn't fall into the 'anything goes' category of UB. – Michael Burr Sep 05 '12 at 21:59
  • 'Requiring a diagnostic doesn't mean that the code must not compile, does it?' -- What the implementation does beyond issuing a diagnostic is beyond the scope of the standard. It could bring about world peace or destroy the planet -- the standard doesn't say. – Jim Balter Sep 08 '12 at 01:33
  • 'C requires diagnostic messages for some, but not all UB' -- this is false; the standard does not require a diagnostic for any UB ... it does not require anything at all, that being the whole point of it being *undefined* behavior. It's also moot, as the answer makes no claims at all about any instance of UB. – Jim Balter Sep 08 '12 at 01:41
13

It signifies that the compiler writer decided on a value of 1 rather than make demons fly from your nose (indeed, it was another undefined use of sizeof that gave us that expression: "the C compiler itself MUST issue a diagnostic IF this is the first required diagnostic resulting from your program, and then MAY itself cause demons to fly from your nose (which, by the way, could well BE the documented diagnostic message) just as it MAY issue further diagnostics for further violations of syntax rules or constraints (or, for that matter, for any reason it chooses)." https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J

From this there's slang term "nasal demons" for whatever a compiler decides to do in response to an undefined construct. 1 is the nasal demon of this compiler for this case.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • @IlmariKaronen I'll have to admit though, that there's a reason most of my answers on C (and C++) are either on general language-agnostic principles or historical nuggets like that. My C experience is bordering on historical in itself :) – Jon Hanna Sep 04 '12 at 22:51
7

As others pointed out, sizeof() can take any valid identifier, but it won't return a valid (an honestly true and valid) result for function names. Furthermore, it definitely may, or may not, result in "demons out of nose" syndrome.

If you want to profile your program function size, check the linker map, which can be found on the intermediate results directory (the one where things are compiled into .obj/.o or where the resulting image/executable lays). Sometimes there's an option to generate or not this map file... it's compiler/linker dependent.

If you wanted the size of a pointer to a function, they're all the same size, the size of an addressing word on your cpu.

jpinto3912
  • 1,457
  • 2
  • 12
  • 19
  • 1
    What sort of statement is "it definitely may or may not"??? Isn't that true of literally everything? – Kerrek SB Sep 04 '12 at 08:33
  • @KerrekSB yes, but here it may or may not do anything, and still be within the rules. It's true a compiler may or may not refuse to compile `int x = 1;` but only one of those is allowed for a standards compliant compiler. With `sizeof()` being applied to a function, it may or may not return a set value, or refuse to compile, or return a random value based on whatever's in a particular register at the time. Literal nasal demons are unlikely, but within the letter of the standard. – Jon Hanna Sep 04 '12 at 08:52
  • @kerrek It may be true for nothing or may not be false for anything... look at it as being fuzzy illogical. – jpinto3912 Sep 04 '12 at 10:25
  • 1
    If you want to know the size of a pointer to a function, apply `sizeof` to a pointer to a function. – alexis Sep 04 '12 at 14:01