Why sizeof(main) = 1?

M

Myth__Buster

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.

/* 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
to see sizeof(main) = 1 if at all makes any sense.

((int (*)(void))p)(); // Known to be buggy and wrong.

return 0;
}

Any explanation is cheerful. :)

Cheers.
 
S

Shao Miller

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?

[...]


Any explanation is cheerful. :)

Cheers.

Cheers to you, also.

C has that "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."

If it's somehow still compiling, then what you are getting is undefined
behaviour, which can be anything at all, including behaviour that has no
rationale.

- Shao Miller
 
J

James Kuyper

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.

/* 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
to see sizeof(main) = 1 if at all makes any sense.

((int (*)(void))p)(); // Known to be buggy and wrong.

return 0;
}

Any explanation is cheerful. :)

"Except when it is the operand of the sizeof operator, the _Alignof
operator,65) 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’’." (6.3.2.1p4)

Since this is occurring in the operand of the sizeof operator, no such
conversion occurs. In other words, you're not asking it to give you the
size of a function pointer, you'reasking it to tell you the size of the
function itself, something that has no meaning in C:

"The sizeof operator shall not be applied to an expression that has
function type ..." 6.5.3.4p1

Thus, sizeof(main) is a constraint violation. The only thing required of
a conforming implementation of C that translates such code is that it
produce at least one diagnostic message. If such an implementation
decides, after issuing the mandatory diagnostic, to accept the code, it
can do anything it wants to with it, since the behavior is undefined. It
could have printed out 1, or 10, or -30, or "NaN" or "Inf" or "this code
violates a constraint" or the name of the first person you ever made
love to.
Once your code violates a constraint, there's not much point in worrying
about what happens next; the only proper response to a constraint
violation is to remove it.
 
M

Myth__Buster

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?

Any explanation is cheerful. :)

Cheers to you, also.

C has that "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."

If it's somehow still compiling, then what you are getting is undefined
behaviour, which can be anything at all, including behaviour that has no
rationale.

- Shao Miller

Okay, that's cool to know. :)

Thanks.
 
M

Myth__Buster

"Except when it is the operand of the sizeof operator, the _Alignof
operator,65) 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’’." (6.3.2.1p4)

Since this is occurring in the operand of the sizeof operator, no such
conversion occurs. In other words, you're not asking it to give you the
size of a function pointer, you'reasking it to tell you the size of the
function itself, something that has no meaning in C:

"The sizeof operator shall not be applied to an expression that has
function type ..." 6.5.3.4p1

Thus, sizeof(main) is a constraint violation. The only thing required of
a conforming implementation of C that translates such code is that it
produce at least one diagnostic message. If such an implementation
decides, after issuing the mandatory diagnostic, to accept the code, it
can do anything it wants to with it, since the behavior is undefined. It
could have printed out 1, or 10, or -30, or "NaN" or "Inf" or "this code
violates a constraint" or the name of the first person you ever made
love to.
Once your code violates a constraint, there's not much point in worrying
about what happens next; the only proper response to a constraint
violation is to remove it.

". . . or the name of the first person you ever made love to." - how
imaginative
you are! :)

Okay, thanks for the explanation.
 
S

Shao Miller

Okay, that's cool to know. :)

You might very well be right about the relationship to GCC's:

void * ptr = &ptr;
ptr++;

allowance, which is a GCC extension, presumably so that something
possibly useful and possibly expected happens, though it's non-standard.

The source code for GCC probably reveals more than a guess could, and
you might be right: It might be that incomplete object types and
function types are treated in this manner, regarding "size."

If you are interested in standard behaviour, you might consider
compiling your test-cases with something like:

gcc -std=c99 -pedantic -Wall -Wextra -o progname progname.c

(Or '-std=c89', for an older standard.) Note that C11 is the current
standard, but I don't know how far along GCC support for it is.

- Shao Miller
 
M

Myth__Buster

You might very well be right about the relationship to GCC's:

   void * ptr = &ptr;
   ptr++;

Nice, self-pointer trick! :)
allowance, which is a GCC extension, presumably so that something
possibly useful and possibly expected happens, though it's non-standard.

The source code for GCC probably reveals more than a guess could, and
you might be right: It might be that incomplete object types and
function types are treated in this manner, regarding "size."

Yeah, seems like it opens up doors for wild guesses though! :)
If you are interested in standard behaviour, you might consider
compiling your test-cases with something like:

   gcc -std=c99 -pedantic -Wall -Wextra -o progname progname.c

(Or '-std=c89', for an older standard.)  Note that C11 is the current
standard, but I don't know how far along GCC support for it is.

- Shao Miller

Okay. Yeah, we can use those compilation flags to stick to the
standards.

Cheers.
 
K

Keith Thompson

Myth__Buster said:
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?
[...]

gcc, as a non-standard extension, permits arithmetic on pointers of
type void* and on function pointers. The semantics are that adding
1 to such a pointer yields a pointer to the immediately following
byte address in memory.

Unfortunately, IMHO, it does this by pretending that both void and
function types have a size of 1.

If you invoke gcc with the right options, it will warn about attempts
to apply sizeof to void or to type or expression of function type.
 
M

Myth__Buster

Myth__Buster said:
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?

[...]

gcc, as a non-standard extension, permits arithmetic on pointers of
type void* and on function pointers.  The semantics are that adding
1 to such a pointer yields a pointer to the immediately following
byte address in memory.

Unfortunately, IMHO, it does this by pretending that both void and
function types have a size of 1.

If you invoke gcc with the right options, it will warn about attempts
to apply sizeof to void or to type or expression of function type.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

Yup, got it! Thanks for the info. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top