Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Why sizeof(main) = 1?

453 views
Skip to first unread message

Barry Schwarz

unread,
Feb 26, 2013, 11:51:20 AM2/26/13
to
On Fri, 4 Jan 2013 18:14:52 -0600 (CST), Myth__Buster
<raghav...@gmail.com> wrote:

>Hi,
>
>On a Linux system with gcc, I am just wondering why sizeof(main) can
>be 1 or sizeof when applied on any function name can yield 1 ever? Or
>is it only gcc's perspective to say sizeof of an implicit function
>pointer to be 1 since it gives sizeof(void) to be 1 based on the
>backward compatibility with the pre C99 notion that void* had its
>predecessor char* and usually sizeof(char) being 1?

sizeof(char) is always 1, not just usually. Why do you think
sizeof(char) being 1 has any effect on sizeof(void*) or sizeof(char*)?

>Also, I tried the invariably buggy code to see if at all sizeof(main)
>= 1 can be realized.
>
>/* Keep the warnings aside for a minute, please! */
>#include <stdio.h>
>
>int main(void)
>{
> printf("sizeof(char) : %zd\n", sizeof(char));
> printf("sizeof(main) : %zd\n", sizeof(main));

This second argument contains a constraint violation and therefore
requires a diagnostic. (The sizeof operator cannot be applied to an
expression of type function.) After that, there is no correct result
so 1 is as good as any other value.

> char p = main; // Truncates into only one byte of the bytes

This assignment also contains a constraint violation and requires a
diagnostic. (There is no implicit conversion from function pointer
to char.)

>required to hold
> // main's address - known bug. But just
>to see sizeof(main) = 1 if at all makes any sense.
>
> ((int (*)(void))p)(); // Known to be buggy and wrong.

This is a syntactically valid statement but since the value in p does
not actually point to a function, once the statement executes you have
undefined behavior.

> return 0;
>}
>
>Any explanation is cheerful. :)

Step outside the language and get strange results. Why are you
surprised?

--
Remove del for email
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.

Gordon Burditt

unread,
Feb 26, 2013, 11:51:34 AM2/26/13
to
> On a Linux system with gcc, I am just wondering why sizeof(main) can
> be 1 or sizeof when applied on any function name can yield 1 ever? Or

I would prefer that sizeof(a_function_name) be 0/0 . Or, for systems
with integer NaNs, (0/0)/(0/0) .

Another value that would make sense is the size of a function pointer
(which is rarely 1) since the use of main in an expression decays
into a function pointer type. If you depend on a particular value
in this situation, you get what you deserve.

sizeof() is not defined on a function type (function *pointers*, yes,
function type, no).

> is it only gcc's perspective to say sizeof of an implicit function
> pointer to be 1 since it gives sizeof(void) to be 1 based on the
> backward compatibility with the pre C99 notion that void* had its
> predecessor char* and usually sizeof(char) being 1?

sizeof(char) is defined as being 1 by the C standard. That should
make sizeof(char) == 1 more often than "usually" for much the same
reason that 2 + 2 usually equals 4 when calculating with ints. I
don't see the backwards compatability issue, but it may have been
more important 20 years ago and from then on it's done for compatability
with previous versions of gcc.

> Also, I tried the invariably buggy code to see if at all sizeof(main)
> = 1 can be realized.
>
> /* Keep the warnings aside for a minute, please! */
> #include <stdio.h>
>
> int main(void)
> {
> printf("sizeof(char) : %zd\n", sizeof(char));
> printf("sizeof(main) : %zd\n", sizeof(main));
>
> char p = main; // Truncates into only one byte of the bytes
> required to hold
> // main's address - known bug. But just

If you mean known bug *with this example*, fine. If you mean known
bug in a particular compiler, I don't see it.

> to see sizeof(main) = 1 if at all makes any sense.
>
> ((int (*)(void))p)(); // Known to be buggy and wrong.
>
> return 0;

Jasen Betts

unread,
Feb 26, 2013, 11:51:25 AM2/26/13
to
On 2013-01-05, Myth__Buster <raghav...@gmail.com> wrote:
> Hi,
>
> On a Linux system with gcc, I am just wondering why sizeof(main) can
> be 1 or sizeof when applied on any function name can yield 1 ever? Or
> is it only gcc's perspective to say sizeof of an implicit function
> pointer to be 1 since it gives sizeof(void) to be 1 based on the
> backward compatibility with the pre C99 notion that void* had its
> predecessor char* and usually sizeof(char) being 1?

1 seems as good as any other value,

> Any explanation is cheerful. :)

C99 6.5.3.4.1 forbids using sizeof with a function type, but does not
require a dignostic (error or warning) from the compiler if it is
attempted.


--
⚂⚃ 100% natural

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Keith Thompson

unread,
Mar 11, 2013, 7:25:37 PM3/11/13
to
Barry Schwarz <schw...@dqel.com> writes:
> On Fri, 4 Jan 2013 18:14:52 -0600 (CST), Myth__Buster
> <raghav...@gmail.com> wrote:
>>On a Linux system with gcc, I am just wondering why sizeof(main) can
>>be 1 or sizeof when applied on any function name can yield 1 ever? Or
>>is it only gcc's perspective to say sizeof of an implicit function
>>pointer to be 1 since it gives sizeof(void) to be 1 based on the
>>backward compatibility with the pre C99 notion that void* had its
>>predecessor char* and usually sizeof(char) being 1?
>
> sizeof(char) is always 1, not just usually. Why do you think
> sizeof(char) being 1 has any effect on sizeof(void*) or sizeof(char*)?
>
>>Also, I tried the invariably buggy code to see if at all sizeof(main)
>>= 1 can be realized.
>>
>>/* Keep the warnings aside for a minute, please! */
>>#include <stdio.h>
>>
>>int main(void)
>>{
>> printf("sizeof(char) : %zd\n", sizeof(char));
>> printf("sizeof(main) : %zd\n", sizeof(main));
>
> This second argument contains a constraint violation and therefore
> requires a diagnostic. (The sizeof operator cannot be applied to an
> expression of type function.) After that, there is no correct result
> so 1 is as good as any other value.
[...]

I can't see the parent article, which was probably posted some time ago,
with responses appearnig only now because comp.lang.c.moderated tends to
have a rather long latency. Quite possibly the answer has already been
posted, but I don't see it here, so ...

gcc supports arithmetic on void* and on pointer-to-function types as a
language extension. In standard C, any attempt to perform pointer
arithmetic on a function pointer or on a pointer to an incomplete type
(such as void*) is a constraint violation, requiring a diagnostic.

gcc is *not* a conforming compiler by default. If you provide the right
command-line options (something like "-std=cXX -pedantic", where XX can
be 89, 99, or 11), then it attempt to be conforming and will warn about
such things.

But wait, you're not performing pointer arithmetic, so why does this
matter? C defines pointer arithmetic in terms of the size of the
poitner's referenced type. The expression `main` is of
pointer-to-function type in this context. The gcc developers decided to
make `sizeof main` 1; the behavior of pointer arithmitec on a
pointer-to-function type follows from that. So `main + 1` is a function
pointer that points one byte *after* the address of the main function.

But only in GNU C; in standard C `main + 1` is nonsense.

IMHO this gcc extension provides a very small amount of convenience for
non-portable code at the expense of a great deal of confusion.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

kzelec...@e3tech.local

unread,
Sep 2, 2013, 5:07:56 AM9/2/13
to
(sizeof main == 1) because (main) is treated as a logical value. Compare:
{ if (main) yadda; }

Użytkownik "Myth__Buster" napisał w wiadomości grup
dyskusyjnych:clcm-2013...@plethora.net...

Hi,

On a Linux system with gcc, I am just wondering why sizeof(main) can
be 1 or sizeof when applied on any function name can yield 1 ever? Or
is it only gcc's perspective to say sizeof of an implicit function
pointer to be 1 since it gives sizeof(void) to be 1 based on the
backward compatibility with the pre C99 notion that void* had its
predecessor char* and usually sizeof(char) being 1?

Also, I tried the invariably buggy code to see if at all sizeof(main)
= 1 can be realized.

James Kuyper

unread,
Sep 7, 2013, 12:25:06 AM9/7/13
to
On 09/02/2013 05:07 AM, kzelec...@e3tech.local wrote:
> (sizeof main == 1) because (main) is treated as a logical value. Compare:
> { if (main) yadda; }

Why are you resurrecting a thread that started eight months ago, and was
completely resolved six months ago?

The behavior of an if() statement depends upon whether the if-condition
compares equal to 0. You could think of if(main) as if it evaluates
main==0, though that's not how the C standard describes it. You might
think that an equality comparison expression should have "a logical
value" - but this is C, and as originally designed, C didn't have have a
logical type (_Bool was a late addition, in C99). In C the expression
main==0 has the type 'int' It's possible that sizeof(int)==1, but it's
not exactly common. For that matter, the standard doesn't say anything
about sizeof(_Bool), either; it could be > 1.

The if(main) example relies upon the fact that "... a function
designator with type ‘‘function returning type’’ is converted to an
expression that has type ‘‘pointer to function returning type’’."
(6.3.2.1p4). However, the "..." in the above citation represents the
following words: "Except when it is the operand of the sizeof operator,
the _Alignof operator,65) or the unary & operator, ...". Therefore, no
such conversion occurs in the sizeof expression (this is from n1570.pdf,
the final draft of C2011 - I think _Alignof may have been removed from
that sentence in the actual standard).
In fact, such code violates a constraint: "The sizeof operator shall not
be applied to an expression that has function type, ..." (6.5.3.4p1)

I you had bothered to read Jason Betts' response, you would already be
aware of (6.5.3.4p1). He said that it "... does not require a dignostic
...", but I'm afraid that's true only because he misspelled diagnostic.
6.5.3.4 is a Constaints* section. At least one diagnostic is required
for any program that violates a constraint.

* - spelling complaints are required to contain at least one spelling
mistake.
--
James Kuyper

Keith Thompson

unread,
Sep 7, 2013, 12:25:44 AM9/7/13
to
<kzelec...@e3tech.local> writes:
> (sizeof main == 1) because (main) is treated as a logical value. Compare:
> { if (main) yadda; }

No, that's not the reason.

Consider that an `int` can also be treated as a logical value;
`if (1)` is valid, but `sizeof 1` is the same as `sizeof (int)`,
which is rarely 1.

The expression `main`, or any function name, is implicitly converted,
in most contexts, to a pointer whose type depends on how you declared
and/or defined the function.

Any pointer value can be used as a condition; it's implicitly
checked for inequality to 0, i.e., to the null pointer.

if (main) yadda;

is well defined but not useful, since `main`, after conversion,
can never be a null pointer.

But when it's the argument of `&` or `sizeof`, this implicit
conversion doesn't happen. `&main` gives you the address of the
`main` function, just like `main` by itself does. `sizeof main`
*would* be the size of a function, but there is no such concept in C,
so it's a constraint violation, requiring a diagnostic.

> Użytkownik "Myth__Buster" napisał w wiadomości grup
> dyskusyjnych:clcm-2013...@plethora.net...
>
> On a Linux system with gcc, I am just wondering why sizeof(main) can
> be 1 or sizeof when applied on any function name can yield 1 ever? Or
> is it only gcc's perspective to say sizeof of an implicit function
> pointer to be 1 since it gives sizeof(void) to be 1 based on the
> backward compatibility with the pre C99 notion that void* had its
> predecessor char* and usually sizeof(char) being 1?
>
> Also, I tried the invariably buggy code to see if at all sizeof(main)
> = 1 can be realized.

I think you mean pre C89 or pre-C90. C89/C90 introduced the `void`
keyword and the `void*` pointer type; C99 didn't make any real
changes in that area. But this has nothing to do with backward
compatibility; the same standard that introduced the `void` keyword
and type also prohibited applying `sizeof` to it.

(And `sizeof (char) == 1` by definition.)

`sizeof main == 1` because of a gcc extension. Standard C does
not permit pointer arithmetic on void* or on function pointers.
Gcc permits both, and specifies that, for example, adding 1 to a
void* or function pointer advances it by one byte (like adding 1 to
a char*). The authors of gcc chose to implement this by pretending
that the size of the type `void`, and the size of any function type,
is 1 (neither has a defined size in standard C).

I can see that pointer arithmetic on `void*` might be convenient in
some cases. The usefulness of arithmetic on function pointers is
less obvious, but I suppose it could have its uses. It's a pity
that implementing such arithmetic had the size effect of making
both `sizeof (void)` and `sizeof main` equal to 1; both results
are nonsensical.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ken Brody

unread,
Sep 7, 2013, 12:25:51 AM9/7/13
to
On 9/2/2013 5:07 AM, kzelec...@e3tech.local wrote:
> (sizeof main == 1) because (main) is treated as a logical value. Compare: {
> if (main) yadda; }

No, it is 1 because gcc has decided that, as an extension to the C standard,
it will allow sizeof to be applied to functions, and will be the value 1.

6.5.3.4p1 states:

"The sizeof operator shall not be applied to an expression that has
function type or an incomplete type, to the parenthesized name of
such a type, or to an expression that designates a bit-field member."

I believe that the name of a function is an "expression that has function
type". (Though I'm sure I will be quickly corrected if I am mistaken.)

If I try compiling the following code:

====
extern void foo(void);
int x = (int)sizeof foo;
====

I get the error:

'void (__cdecl *)(void)': illegal sizeof operand

Keith Thompson

unread,
Sep 11, 2013, 6:26:47 PM9/11/13
to
James Kuyper <james...@verizon.net> writes:
> On 09/02/2013 05:07 AM, kzelec...@e3tech.local wrote:
>> (sizeof main == 1) because (main) is treated as a logical value. Compare:
>> { if (main) yadda; }
>
> Why are you resurrecting a thread that started eight months ago, and was
> completely resolved six months ago?
>
> The behavior of an if() statement depends upon whether the if-condition
> compares equal to 0. You could think of if(main) as if it evaluates
> main==0, though that's not how the C standard describes it.

Or you could think of it as if it evaluates main!=0 -- which very nearly
is how the C standard describes it:

In both forms [of the "if" statement], the first substatement is
executed if the expression compares unequal to 0

Since the expression main decays to a pointer, the 0 is treated as a
null pointer constant and is converted to the same pointer type.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Robert Wessel

unread,
Sep 11, 2013, 6:27:31 PM9/11/13
to
On Fri, 6 Sep 2013 23:25:44 -0500 (CDT), Keith Thompson
<ks...@mib.org> wrote:

>The expression `main`, or any function name, is implicitly converted,
>in most contexts, to a pointer whose type depends on how you declared
>and/or defined the function.
>
>Any pointer value can be used as a condition; it's implicitly
>checked for inequality to 0, i.e., to the null pointer.
>
> if (main) yadda;
>
>is well defined but not useful, since `main`, after conversion,
>can never be a null pointer.


Is that actually true? Certainly any valid data-type object cannot
have an address of zero/NULL, but is that true of function objects?

James Kuyper

unread,
Sep 12, 2013, 12:29:08 PM9/12/13
to
On 09/11/2013 06:26 PM, Keith Thompson wrote:
> James Kuyper <james...@verizon.net> writes:
>> On 09/02/2013 05:07 AM, kzelec...@e3tech.local wrote:
>>> (sizeof main == 1) because (main) is treated as a logical value. Compare:
>>> { if (main) yadda; }
>>
>> Why are you resurrecting a thread that started eight months ago, and was
>> completely resolved six months ago?
>>
>> The behavior of an if() statement depends upon whether the if-condition
>> compares equal to 0. You could think of if(main) as if it evaluates
>> main==0, though that's not how the C standard describes it.
>
> Or you could think of it as if it evaluates main!=0 -- which very nearly
> is how the C standard describes it:
>
> In both forms [of the "if" statement], the first substatement is
> executed if the expression compares unequal to 0
>
> Since the expression main decays to a pointer, the 0 is treated as a
> null pointer constant and is converted to the same pointer type.

My key point was that the description of the semantics of an if()
statement are not related to the rules governing the type of the result
of a comparison expression (whether it's an equality or inequality
expression is irrelevant to my point). Thus, connecting the value of
"sizeof main" to the semantics of if(main) is meaningless (and not just
for this reason - my full message gave other, more important reasons).
--
James Kuyper

James Kuyper

unread,
Sep 12, 2013, 12:29:41 PM9/12/13
to
On 09/11/2013 06:27 PM, Robert Wessel wrote:
> On Fri, 6 Sep 2013 23:25:44 -0500 (CDT), Keith Thompson
> <ks...@mib.org> wrote:
...
>> if (main) yadda;
>>
>> is well defined but not useful, since `main`, after conversion,
>> can never be a null pointer.
>
>
> Is that actually true? Certainly any valid data-type object cannot
> have an address of zero/NULL, but is that true of function objects?

"a null pointer ... is guaranteed to compare unequal
to a pointer to any object or function." (6.3.2.3p3)
"Two pointers compare equal if ... both are null pointers." (6.5.9p6)
If a pointer to main were a null pointer, those two requirements would
be in conflict.
--
James Kuyper

Keith Thompson

unread,
Sep 12, 2013, 12:30:18 PM9/12/13
to
Robert Wessel <robert...@yahoo.com> writes:
> On Fri, 6 Sep 2013 23:25:44 -0500 (CDT), Keith Thompson
> <ks...@mib.org> wrote:
>>The expression `main`, or any function name, is implicitly converted,
>>in most contexts, to a pointer whose type depends on how you declared
>>and/or defined the function.
>>
>>Any pointer value can be used as a condition; it's implicitly
>>checked for inequality to 0, i.e., to the null pointer.
>>
>> if (main) yadda;
>>
>>is well defined but not useful, since `main`, after conversion,
>>can never be a null pointer.
>
> Is that actually true? Certainly any valid data-type object cannot
> have an address of zero/NULL, but is that true of function objects?

Yes. N1570 6.3.2.3p3 says that a null pointer is guaranteed to
compare unequal to a pointer to any object or function.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
0 new messages