I have a hard time understanding sizeof
\'s behaviour when given a ternary expression.
#define STRING \"a s
You need to understand that sizeof
is entirely a compile-time operator.
With VLA it could return a variable expression, otherwise it is a compile-time constant.
What matters is the type of its argument.
So in sizeof(argc > 1 ? STRING : "")
the condition is not evaluated. The type of the argument is decayed to const char*
. And on your machine, it is 4.
You should code instead (argc > 1)?sizeof(STRING):1
Since STRING
is macro-expanded to the "a string"
literal, sizeof(STRING)
is 9, nearly as if you have declared
const char STRING[] = {'a',' ','s','t','r','i','n','g','\0'};
Both STRING
and ""
are array objects of types char[9]
and char[1]
respectively. In C language, when array objects are used in expressions, they get implicitly converted (decay) to pointer types in almost all contexts, with few well-known specific exceptions.
One of such exceptions is sizeof
operator. When you use an array object as an immediate operand of sizeof
that array object does not decay to pointer type, and you get the size of the entire array in bytes as result. This is why sizeof(STRING)
is equivalent to sizeof(char[9])
and evaluates to 9
. And sizeof("")
is equivalent to sizeof(char[1])
and evaluates to 1
.
But when you use array objects as operands of ?:
operator, the context is no longer exceptional. In context of ?:
operator arrays immediately decay to pointers. This means that your sizeof(argc > 1 ? STRING : "")
is equivalent to sizeof(argc > 1 ? (char *) STRING : (char *) "")
, and in turn equivalent to sizeof(char *)
. This evaluates to pointer size on your platform, which just happens to be 4
.
You have to understand expressions, which are the core component of the language.
Every expression has a type. For an expression e
, sizeof e
is the size of the type of the value of the expression e
.
The expression a ? b : c
has a type. The type is the common type of the two operand expressions b
and c
.
In your example, the common type of char[9]
and char[1]
is char *
(both array-valued expressions decay to a pointer to the first element). (In C++, the rules for string literals are different and there is a const
everywhere.)