6

Why do we say sizeof(variable) is an operator, not a function?

It looks like a function call and when I am thinking about the meaning of operator, it appears to me something like + or - or * and so on

phuclv
  • 37,963
  • 15
  • 156
  • 475
Run
  • 130
  • 6

7 Answers7

7

It's an operator, and you don't need to use brackets, except "when the operand is a type name, it must be enclosed in parentheses". This is a syntax restriction, but should not be confused with a function call.

See the last example below from the GNU documentation:

size_t a = sizeof(int);
size_t b = sizeof(float);
size_t c = sizeof(5);
size_t d = sizeof(5.143);
size_t e = sizeof a;

Without parentheses for a type name, you may see an error like this, with the gcc compiler:

test.c:7:20: error: expected expression before ‘int’
    7 |  size_t s = sizeof int;
      |                    ^~~

But doing sizeof 12 or sizeof a is fine.

Nagev
  • 10,835
  • 4
  • 58
  • 69
5

It's an operator because it doesn't take arguments like a function does. It operates at the syntax level.

f(int) is not a valid function call, but sizeof(int) is a valid use of sizeof.

It can also operate on variables or types, it's quite flexible by design, which is something an operator can do as it's baked deep into the C syntax.

More details can be found here.

tadman
  • 208,517
  • 23
  • 234
  • 262
3

As the grammar indicates:

unary-expression:
  postfix-expression
  ++ unary-expression
  -- unary-expression
  unary-operator cast-expression
  sizeof unary-expression
  sizeof (type-name)
  _Alignof (type-name)

unary-operator: one of
  & * + - ~ !

it's an operator that not only does not require parentheses when taking an unary-expression argument, but it behaves differently with parentheses than a function call would.

Consider that given _Static_assert(sizeof(0)==4,"");, the following holds:

_Static_assert(sizeof(0)==4,"");
int takeIntGive4(int X){ (void)X; return 4; }

#include <assert.h>
int main()
{
    assert(sizeof(0)["foobar"] == 1  && 1 == sizeof(char)); //if sizeof were more function-like you'd get 'a'
    assert(takeIntGive4(0)["foobar"] == 'a');
}

In other words, even though sizeof(0) == takeIntGive4(0) is true on this platform, you can't always just replace takeIntGive4(0) with sizeof(0) because sizeof has a lower precedence than a function call and sizeof(0)["foobar"] will be interpreted as sizeof( (0)["foobar"] ), not (sizeof(0))["foobar"] like it would be if sizeof() were a function.

You can make sizeof function-like, by wrapping it in a macro that parenthesizes it:

#define SIZEOF(X) (sizeof(X))

but keep in mind that sizeof also additionally returns integer constant expressions (except when used with variable-length arrays (VLAs)), which you can use in case labels, bitfield sizes, and array sizes and which function call expressions are incapable of returning.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
2

It is an operator because it is built into the language. Just like + or < it is included in the language grammar. Because of this the sizeof operator can be evaluated when a program is compiled, unlike a user-defined function. For example we can define a function macro which returns the length of a (non-variable length) array:

#define LENGTH(array) (sizeof (array) / sizeof (array)[0])

The length expression is calculated when the program is compiled. At run-time the length of an array is not available (unless you store it in a separate variable).

August Karlstrom
  • 10,773
  • 7
  • 38
  • 60
2

It's an operator that's evaluated at compile-time.

In fact, it only requires the function-like syntax sizeof(T) when T is a type and not an instance of a type.

So, for example, if you have a variable int x, sizeof x is permissible; but sizeof(int) is required for the type int.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • 1
    `sizeof` is a compile time constant (technically: necessarily qualifies as an integer constant) only if its operand does not have variable length array type. – Eric Postpischil Jan 22 '21 at 15:56
1

sizeof is an operator. It is listed among the list of unary operators in section 6.5.3p1 of the C standard:

6.5.3 Unary operators

Syntax

unary-expression:
  postfix-expression
  ++ unary-expression
  -- unary-expression
  unary-operator cast-expression
  sizeof unary-expression
  sizeof (type-name)
  _Alignof (type-name)

unary-operator: one of
  & * + - ~ !

As shown above it has two forms. The first form is sizeof followed by an expression. Note that in this form parenthesis are not required, unlike in a function call where they are. The second form is sizeof followed by a type name in parenthesis. Only the second form requires parenthesis, and a function cannot be passed a type name.

It is further referred to as an operator in section 6.5.3.4:

6.5.3.4 The sizeof and _Alignof operators

...

2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. 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

dbush
  • 205,898
  • 23
  • 218
  • 273
0

Is sizeof a function or an operator?
Why we said sizeof(variable) is operator not function?

In addition to what other have answered, code can take the address of a function, but not the address of sizeof. Much like can cannot take the address of = or *.

size_t (*f1)() = strlen;
size_t (*f2)() = sizeof;
//                     ^ error: expected expression before ';' token

With objects, the () are not needed with sizeof, unlike a function call.

char array[42];
size_t n1 = sizeof array;
size_t n2 = strlen(array) + 1;
 

sizeof can be used with types, not so with a function call.

size_t sz1 = sizeof(double);
size_t sz2 = printf(double);
//                  ^ error: expected expression before 'double'
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256