0

I have two functions without any implementation.

I expect that the linker returns an undefined reference to hello and world error.

But surprisingly, the code compiles and runs without any error.

#include <stdio.h>

int hello();
char world();

int main() {
  printf("sizeof hello = %zu, sizeof world = %zu\n", sizeof(hello()), sizeof(world()));
}
sizeof hello = 4, sizeof world = 1
Nader
  • 318
  • 1
  • 6
  • 16
  • 1
    You don't need the definition to tell what the return type is. – HolyBlackCat Feb 08 '23 at 12:12
  • 1
    The size of what a function returns does not depend on its definition. – Jesper Juhl Feb 08 '23 at 12:17
  • 2
    "When applied to an expression, `sizeof` does not evaluate the expression (i.e. the expression is an unevaluated operand)". In other words, `sizeof` looks at the tins label but not the contents inside the tin – WBuck Feb 08 '23 at 12:18
  • `sizeof()` returns `size_t`, not `long int`. The correct format specifier for `size_t` is `%zu`. `%ld` is wrong, and while it might work on Linux or other systems, it *will* emit wrong data on 64-bit Windows, where `long int` is only 32 bits. – Andrew Henle Feb 08 '23 at 12:20
  • 1
    Remember that `sizeof` is a **keyword**, not a **function**. `sizeof(f())` will not evaluate `f()`. – wtz Feb 08 '23 at 12:40
  • https://softans.com/question/how-sizeof-works-on-unimplemented-function/#comment-483 – GHULAM NABI Feb 08 '23 at 12:59

3 Answers3

12

sizeof(hello()) is the size of the the return type, int, not the size of the function. The function is not called.

The function does not need to be defined to determine its return type declared by int hello();.


Deeper (in C)

sizeof works with sizeof unary-expression and sizeof ( type-name ).

The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant. C17dr § 6.5.3.4 2

Since the type of the operand hello() is an int (and not a variable length array), the operand is not evaluated and is then like sizeof(int).


Aside: sizeof returns a size_t.

"%zu" is a correct specifier to match a size_t. "%ld" is not specified to work.

// printf("sizeof hello = %ld, sizeof world = %ld\n", sizeof(hello()), sizeof(world()));
printf("sizeof hello = %zu, sizeof world = %zu\n", sizeof(hello()), sizeof(world()));
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3

sizeof is unevaluated context. It does not actually call the functions. No definition is required. The declaration is sufficient to know that they return int and char.

You could as well have written sizeof(int) and sizeof(char) to get the same output. sizeof(&hello) would result in the size of a function pointer to hello and does not require the definition either. And sizeof(hello) just makes no sense, because functions have no size (at least not in a sense that sizeof could tell you).

For details I refer you to https://en.cppreference.com/w/cpp/language/sizeof (c++) and https://en.cppreference.com/w/c/language/sizeof (c).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

The title of your question:

how sizeof works on unimplemented function?

implies you are trying to determine how much memory the function implementation uses, similar to sizeof() int returning how much memory an int variable uses.

You can't use sizeof() on a function like that.

Per 6.5.3.4 The sizeof and _Alignof operators, paragraph 1 of the (draft) C11 standard:

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

The draft C23 standard has the exact same wording:

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

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56