Regarding the sizeof a function

V

venkat

Hi,

I have written a program

void main()
{
printf("%d %d\n", sizeof main, sizeof(main()));
}

in this program the output is 1 and 4,

as i understood from the books, function name represents the address
of the function. i thought sizeof main should give 4 , and i don't
know why sizeof(main()) is giving 4, Can some one please explain what
the former one does and what the later one do?. Why is this behavior?

Appreciate your help in this regard.

Thanks,
Vikas.
 
R

Richard Tobin

venkat said:
printf("%d %d\n", sizeof main, sizeof(main()));

There are several other errors in your program, but

(a) Functions are not converted to function pointers when
used as the operand of sizeof. It's illegal to apply
sizeof to a function.

(b) It's illegal to apply sizeof to void, since it's an
incomplete type.

-- Richard
 
V

venkat

There are several other errors in your program, but

(a) Functions are not converted to function pointers when
used as the operand of sizeof. It's illegal to apply
sizeof to a function.

(b) It's illegal to apply sizeof to void, since it's an
incomplete type.

-- Richard

Hi Richard,

Thanks for replying, i haven't observed that much, i want to avoid the
return that is why i put void in the program , the program is give
below

main()
{
printf("%d %d\n", sizeof main, sizeof(main()));

return;

}
 
R

Richard Heathfield

venkat said:

Thanks for replying, i haven't observed that much, i want to avoid the
return that is why i put void in the program ,

But by doing so, you are no longer writing in C.
the program is give below

main()
{
printf("%d %d\n", sizeof main, sizeof(main()));

Undefined behaviour because you call a variadic function without a valid
prototype in scope. Solution: #include <stdio.h>

Undefined behaviour because you're passing size_t to printf when it's
expecting int. You do this twice. Solution: add casts to int. (A rare
correct use of a cast.)

Constraint violation requiring a diagnostic message because you're
trying to apply sizeof to an expression having function type. Solution:
don't apply sizeof to an expression having function type.
 
C

CBFalconer

venkat said:
.... snip ...

Thanks for replying, i haven't observed that much, i want to avoid
the return that is why i put void in the program , the program is
give below

main()
{
printf("%d %d\n", sizeof main, sizeof(main()));
return;
}

main returns an int. Say and do so. #include <stdio.h>. A call
to a variadic function without a prototype is an error, and
behaviour is undefined. sizeof can't be applied to functions.
 
B

Barry Schwarz

Hi,

I have written a program

void main()
{
printf("%d %d\n", sizeof main, sizeof(main()));
}

in this program the output is 1 and 4,

as i understood from the books, function name represents the address
of the function. i thought sizeof main should give 4 , and i don't
know why sizeof(main()) is giving 4, Can some one please explain what
the former one does and what the later one do?. Why is this behavior?

Appreciate your help in this regard.

Your understanding is incorrect at several points.

When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to function.

The operand of the sizeof operator is not evaluated. The
compiler merely determines the type.

The sizeof operator may not be applied to a function or to an
incomplete type.

Now look at your code.

main should return int.

You have no prototype for printf. Calling a variadic function
this way invokes undefined behavior.

Your second argument applies sizeof to a function. This
invokes undefined behavior.

Your format string promises that the third argument is of type
int. Your actual argument is of type size_t. More undefined
behavior.

In your code, the type of main() is void. void is an
incomplete type. More undefined behavior.

Since your code invokes undefined behavior, there is no way to explain
why it produced this output. There is no guarantee that it would
produce the same behavior if you reran it.

Your third argument


Remove del for email
 
K

Keith Thompson

venkat said:
I have written a program

void main()
{
printf("%d %d\n", sizeof main, sizeof(main()));
}

in this program the output is 1 and 4,

as i understood from the books, function name represents the address
of the function. i thought sizeof main should give 4 , and i don't
know why sizeof(main()) is giving 4, Can some one please explain what
the former one does and what the later one do?. Why is this behavior?

The correct declaration is "int main(void)"; your compiler might
happen to allow "void main()", but it's non-standard and non-portable.
Writing non-standard code for the sake of avoiding a return statement
isn't worth it; just add a "return 0;" at the end. (The "return 0;"
might not be necessary, but it can't hurt.)

Since you call printf(), you need to add "#include <stdio.h>". This
is another of those things that's mandatory, but your compiler might
not be friendly enough to warn you about it.

It's illegal (a constraint violation, requiring a diagnostic) to apply
sizeof to a function name. It's also illegal to apply sizeof to an
expression of type void (you declared main() to return void, so the
expression main() is of type void). Your compiler may be allowing
these applications of sizeof as a non-portable extension. (gcc has
such an extension, but the output you're seeing is inconsistent with
the way gcc does this.)

printf's "%d" format expects an int argument; sizeof yields a value of
type size_t. If the rest of the program weren't incorrect, you could
avoid that problem by casting the arguments to type int.

Here's a corrected version of your program:

#include <stdio.h>
int main(void)
{
printf("%d %d\n", (int)sizeof &main, (int)sizeof main());
return 0;
}

This will print two numbers, the size in bytes of a function pointer
and the size in bytes of an int. I get "4 4" on one system, "8 4" on
another; there are other possibilities.

Here's an exercise for you. Read your compiler's documentation and
find out how to enable warning messages. Using your program as you
posted it, errors and all, figure out how to make your compiler warn
you about *all* the errors I've pointed out. It might not be able to
warn about the mismatch in the printf format, but it should be able to
diagnose the other problems. Once you've found the right set of
options, develop the habit of using them whenever you use the
compiler, and correct any problems it warns you about. And remember
that fixing your code so it doesn't produce any warnings is the only
*beginning* of writing correct code.
 
K

Keith Thompson

Barry Schwarz said:
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator. &func
yields the address of the function; sizeof func, as you mention later,
is a constraint violation.
 
R

Richard Heathfield

Keith Thompson said:
Barry Schwarz said:
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to
function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator.

Read it again, Keith. Neither & nor sizeof evaluate their operands.
Barry was dealing with the evaluation case first, as a sort of "that's
what the OP thought was happening", to lead into his "but this is what
is actually happening" paragraph, which you snipped, but which dealt
with the sizeof issue perfectly well: "The operand of the sizeof
operator is not evaluated. The compiler merely determines the type."
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:
Barry Schwarz said:
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to
function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator.

Read it again, Keith. Neither & nor sizeof evaluate their operands.
Barry was dealing with the evaluation case first, as a sort of "that's
what the OP thought was happening", to lead into his "but this is what
is actually happening" paragraph, which you snipped, but which dealt
with the sizeof issue perfectly well: "The operand of the sizeof
operator is not evaluated. The compiler merely determines the type."

Ok, fair enough.

IMHO the rule as stated in the standard is simpler to understand:
whenever an expression of function type appears (most commonly a
function name), it's converted to a pointer unless it's the operand of
a unary "&" or "sizeof"; for "&", the address is computed, and for
"sizeof", a constraint is violated.

There may be infinitely many ways to express this correctly.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Richard said:
Keith Thompson said:
Barry Schwarz said:
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to
function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator.

Read it again, Keith. Neither & nor sizeof evaluate their operands.

Evaluation of the unary & operator does cause evaluation of its operand, and
the conversion from function to pointer-to-function normally is part even
of expressions that are not evaluated. sizeof(main()) cannot be accepted if
the conversion from int(void) to int(*)(void) gets omitted just because the
expression is not evaluated.
 
P

pete

Harald van =?UTF-8?B?RMSzaw==?= wrote:
Evaluation of the unary & operator
does cause evaluation of its operand,

No it doesn't.
There's no undefined behavior in the code below
even though the value of (A) is indeterminate.

/* BEGIN new.c */

int main(void)
{
int A;
int *B = &A;

return 0;
}

/* END new.c */
 
R

Richard Tobin

Evaluation of the unary & operator
does cause evaluation of its operand,
[/QUOTE]
No it doesn't.

I don't have the standard handy so I can't check its definition of
"evaluate", but there's certainly a sense in which the operand of & is
evaluated, and it's much the same sense in which the left hand side of
an assignment is evaluated. If you have

&(a[3*x]->b)
or
a[3*x]->b = 1

then in both cases all of the "evaluation" of a[3*x]->b is done except
the last step, in order to determine the location referred to.

-- Richard
 
H

Harald van =?UTF-8?B?RMSzaw==?=

pete said:
No it doesn't.

Yes, it does.
There's no undefined behavior in the code below
even though the value of (A) is indeterminate.

/* BEGIN new.c */

int main(void)
{
int A;
int *B = &A;

return 0;
}

/* END new.c */

That's because the lvalue-to-value conversion is not performed. You're just
evaluating something different now: you're evaluating the lvalue A, rather
than the value stored at lvalue A.

The distinction matters: given
struct S { int member; };
struct S *f();

evaluation of &(f()->member) must result in a call to f.
 
K

Keith Thompson

Harald van Dijk said:
Richard said:
Keith Thompson said:
[...]
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to
function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator.

Read it again, Keith. Neither & nor sizeof evaluate their operands.

Evaluation of the unary & operator does cause evaluation of its operand, and
the conversion from function to pointer-to-function normally is part even
of expressions that are not evaluated.

Actually, the operand of unary "&" is evaluated *as an lvalue*. For
example, &array[func()] will call func.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Keith said:
Harald van Dijk said:
Richard said:
Keith Thompson said:
[...]
When an unadorned function name (one without the argument
list) is evaluated, the result is a value of type pointer to
function.
[...]

*Unless* it's the operand of unary "&" or "sizeof" operator.

Read it again, Keith. Neither & nor sizeof evaluate their operands.

Evaluation of the unary & operator does cause evaluation of its operand,
and the conversion from function to pointer-to-function normally is part
even of expressions that are not evaluated.

Actually, the operand of unary "&" is evaluated *as an lvalue*. For
example, &array[func()] will call func.

I'm not sure that's the best example. &array[func()] is equivalent to
&*(array+func()), and for the special case of an unary & operator with an
unary * operator as its operand, neither operator is evaluated.
 
S

Serve Laurijssen

Richard Heathfield said:
venkat said:



But by doing so, you are no longer writing in C.


Undefined behaviour because you call a variadic function without a valid
prototype in scope. Solution: #include <stdio.h>

Undefined behaviour because you're passing size_t to printf when it's
expecting int. You do this twice. Solution: add casts to int. (A rare
correct use of a cast.)

any reason why you dont advice to use %u? or even %zu for c99
 
R

Richard Heathfield

Serve Laurijssen said:
...


any reason why you dont advice to use %u? or even %zu for c99

Yes.

Normally I would advise %lu for C90, and %zu for C99, but I got the
impression that that would be TMI for this particular OP at this stage
in his education.
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top