When should we use sizeof with and without parentheses
When using sizeof
with a type, you need parentheses around the type. When using it with an expression, you don't. But you can of course include them in this case as well, and you don't have to worry about operator precedence in such case. With uncommon operators such as this one, fewer people would be sure of the precedence, so clarity certainly helps.
So I'd say it's preferable to use them always.
Why (and when) do I need to use parentheses after sizeof?
According to 6.5.3, there are two forms for sizeof
as the following:
sizeof unary-expression
sizeof ( type-name )
Since arr
in your code is a type-name
, it has to be parenthesized.
What does sizeof without () do?
So if we look at the grammar for sizeof
in the C99 draft standard section 6.5.3
Unary operators paragraph 1 it is as follows:
sizeof unary-expression
sizeof ( type-name )
There is a difference you can not use a type-name without parenthesizes and section 6.5.3.4
The sizeof operator paragraph 2 says(emphasis mine):
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type.[...]
For completeness sake you may wonder if we can use sizeof
with an expression if we have parenthesizes and the answer is yes since a unary-expression can itself contain parenthesizes. The easiest way to see this would be to look section A.2.1
Expressions from the draft standard and work through the grammar like so:
unary-expression -> postfix-expression -> primary-expression -> ( expression )
The result of sizeof depends on the location of the brackets. Why?
This expression
sizeof x+y
is equivalent to the expression
( sizeof x ) + y
So as sizeof x
is equal to sizeof( float )
that is 4
then the result of the original expression is equal to 9
.
The operator sizeof
is an unary operator and its operand is in turn an unary expression. That is the operator in particularly is defined like
sizeof unary-expression
x + y
is an additive expression while the variable x
as a primary expression is in turn an unary expression. Thus the operator is applied to the variable x.
On the other hand, the expression ( x + y )
is a primary expression and due to the usual arithmetic conversions has the type float
. So in this case that is when the expression is written like sizeof( x + Y )
the operator sizeof
is again applied to a primary (unary) expression and is equivalent to sizeof( float )
.
Pay attention to that instead of the conversion specifier %u
you shall use the conversion specifier %zu
in the calls of printf
. The type of the both expressions sizeof x + y
and sizeof( x + y )
is size_t
that is an implementation defined type that usually is an alias for the type unsigned long
. For the type size_t
there is defined the conversion specifier zu
that you shall use. Otherwise a call of printf
with an incorrect conversion specifier can invoke undefined behavior.
Where does C++20 prohibit sizeof...T (without parentheses)
It's required by the grammar:
[expr.unary.general]/1
unary-expression:
...
sizeof
...
(
identifier)
...
Difference between sizeof(name) and sizeof name
No sizeof
isn't a library function, it's a special operator keyword.
It has two forms: One is with parentheses to get the size of a type. The other is not using parentheses and is for getting the size of the result of a generic expression.
With sizeof(name)
you're really using the second variant, with the expression (name)
. I.e. the parentheses are part of the expression and not the sizeof
operator.
Why is sizeof considered an operator?
Because the C standard says so, and it gets the only vote.
As consequences:
- The operand of sizeof can be a parenthesised type,
sizeof (int)
, instead of an object expression. - The parentheses are unnecessary:
int a; printf("%d\n", sizeof a);
is perfectly fine. They're often seen, firstly because they're needed as part of a type cast expression, and secondly because sizeof has very high precedence, sosizeof a + b
isn't the same assizeof (a+b)
. But they aren't part of the invocation of sizeof, they're part of the operand. - You can't take the address of sizeof.
- The expression which is the operand of sizeof is not evaluated at runtime (
sizeof a++
does not modify a). - The expression which is the operand of sizeof can have any type except void, or function types. Indeed, that's kind of the point of sizeof.
A function would differ on all those points. There are probably other differences between a function and a unary operator, but I think that's enough to show why sizeof could not be a function even if there was a reason to want it to be.
Related Topics
Member Initializer Does Not Name a Non-Static Data Member or Base Class
Concatenate Compile-Time Strings in a Template at Compile Time
In C++, Differencebetween a Method and a Function
Fatal Error C1010 - "Stdafx.H" in Visual Studio How Can This Be Corrected
Using Std::Visit with Variadic Template Struct
Recognize Open and Closed Shapes Opencv
C++ Nested Classes Accessibility
How to Iterate Through a List of Objects in C++
How to Install Llvm Toolchain for Eclipse Cdt
Simple 3X3 Matrix Inverse Code (C++)
Two Dimensional Array Using Vector
Convert a Number to a String with Specified Length in C++