3

size of a function using sizeof() always returns 1

I just tried to find the size of a function.While using sizeof() for finding the size it always returns 1.Even the function is a well defined function it just returns 1. I just wanna know why it returns 1. What actually it considers when saying sizeof(funtion).

consider a simple swap function. I used fun3 just to show the difference of addresses occupied.

void fun1(int a,int b)
{
 int temp;
 temp=a;
 a=i;
 i=b;
 printf("%d\t %d\n",a,b);
}
void fun2()
{

}
void fun3()
{

}
void main()
{
 printf("fun1\t Address : %d \t Size : %d\n",fun1,sizeof(fun1));
 printf("fun2\t Address : %d \t Size : %d\n",fun2,sizeof(fun2));
 printf("fun3\t Address : %d \t Size : %d\n",fun3,sizeof(fun3));
}

the output here is
fun1 Address : 4199248 Size : 1
fun2 Address : 4199301 Size : 1
fun3 Address : 4199307 Size : 1

The number of addresses occupied by fun1 is huge,fun2 occupies only 6.But the Size remains same for both

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    Because the sizeof is 1. – Deanie Dec 27 '18 at 02:15
  • sizeof can be applied to any data-type, including primitive types such as integer and floating-point types, pointer types, or compound datatypes such as Structure, union etc. I don't think it can be applied to functions. http://c0x.coding-guidelines.com/6.5.3.4.html – Vhndaree Dec 27 '18 at 02:20
  • @Fred: No, `sizeof(&fun)` is fine. It's `sizeof(fun)` that's invalid. I think you might have gotten confused by the part about "expressions of function type are specifically not converted to pointers in this situation" in my comment. In most situations, `fun` is automatically treated as equivalent to `&fun`, but not in the case of `sizeof(fun)`; if you want `sizeof(&fun)`, you have to provide the `&` explicitly. – user2357112 Dec 27 '18 at 03:11
  • @user2357112 I originally commented that `sizeof(&fun)` would be fine. But after reading the sections of the spec you pointed out I confused myself. Sorry. – fdk1342 Dec 27 '18 at 03:21

2 Answers2

10

I suspect that there's a long chain of issues here that leads to the answer of "this is undefined behavior."

The first thing to note is that you shouldn't use %d to print out pointers in printf. The %d modifier is for printing ints, and ints aren't always convertible to and from pointers in the usual way. For example, on a 64-bit system, it might be the case that an int is 32 bits and that a pointer is 64 bits, meaning that passing in a pointer to printf and then trying to print it with %d might only print half the bits. You should use the %p specifier any time you want to print out a pointer.

That would suggest that some amount of what you're seeing here might be due to the %d only picking up half the bits from your pointer, which is then leaving the other bits from the pointer getting picked up by the second %d modifier, meaning that the 1 that you're seeing here isn't actually the size of the function pointer, but rather garbage data due to a bad format string. That would be Undefined Behavior - bad times!

Now, how would you go about printing the address of the function itself? The bad news is that there's no portable way to do this. Normally, for pointers, you could just use the %p modifier. But function pointers are unusual in C in that they can't be implicitly converted to normal pointers. That is, you can't portably cast a function pointer to, say, a void * or a void * to a function pointer. The literal reason for this is "because the spec says so," but the deeper reason is that on some non-x86, non-ARM systems functions are stored in a physically different region of memory than data and the pointers have very different binary representations than regular pointers.

There are some heavyweight ways to print out function pointers, but as you can see, it's not easy.

Independently, how should you print out the size of the function pointer? Try this, using the %zu modifier, which is for size_ts:

printf("Function pointer has size %zu\n", sizeof(&fun1));
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 6
    More undefined behavior: in standard C, you can't actually apply `sizeof` to a function. Applying `sizeof` to an expression of function type is a constraint violation, and expressions of function type are specifically not converted to pointers in this situation. ([N1548 draft](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf), sections 6.5.3.4 and 6.3.2.1.) – user2357112 Dec 27 '18 at 02:33
  • @user2357112 To confirm, that doesn't preclude applying `sizeof` to a *pointer* to a function, though, correct? – templatetypedef Dec 27 '18 at 02:47
  • @templatetypedef: Applying `sizeof` to a pointer to a function is fine. – user2357112 Dec 27 '18 at 02:49
  • @templatetypedef True the section "Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type." does imply UB if output out of range, so I'll have to take down the assertion in the comment. – chux - Reinstate Monica Dec 27 '18 at 03:03
  • 1
    .@Fred The language spec (7.20.1.4) only says that `uintptr_t` can hold `void *`s, which doesn't guarantee that this type is big enough to hold a function pointer. – templatetypedef Dec 27 '18 at 03:32
  • @templatetypedef Thanks, sorry for the noise. I did see that [dlsym rationale](http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html) states `The ISO C standard does not require that pointers to functions can be cast back and forth to pointers to data. Indeed, the ISO C standard does not require that an object of type void * can hold a pointer to a function. Implementations supporting the XSI extension, however, do require that an object of type void * can hold a pointer to a function.` Also on linux `dlsym` is defined as return `void *`. It seems to be a POSIX requirement. – fdk1342 Dec 27 '18 at 17:52
-3

because sizeof when fed a pointer returns the size of the pointer not the actualy size of the object. this may help explain things:

https://en.cppreference.com/w/cpp/language/sizeof

  • While this is certainly true, I think the unusual behavior here is due to printing out sizes of functions rather than function pointers, mixed with printf format string issues, rather than due to pointer / pointee confusion. – templatetypedef Dec 27 '18 at 03:35