[英]Operator 'sizeof' with conditional (ternary) expression
I have a hard time understanding sizeof
's behaviour when given a ternary expression. 在给出三元表达式时,我很难理解
sizeof
的行为。
#define STRING "a string"
int main(int argc, char** argv)
{
int a = sizeof(argc > 1 ? STRING : "");
int b = sizeof(STRING);
int c = sizeof("");
printf("%d\n" "%d\n" "%d\n", a, b, c);
return 0;
}
In this example (tested with gcc 4.4.3 and 4.7.2, compiled with -std=c99
), b is 9 (8 characters + implicit '\\0'
), c is 1 (implicit '\\0'
). 在这个例子中(用gcc 4.4.3和4.7.2测试,用
-std=c99
编译),b是9(8个字符+隐式'\\0'
),c是1(隐式'\\0'
)。 a, for some reason, is 4 . a,出于某种原因,是4 。
I would expect a to be either 9 or 1, based on whether argc is greater than 1. I thought maybe the string literals get converted to pointers before being passed to sizeof
, causing sizeof(char*)
to be 4. 根据argc是否大于1,我希望a为9或1.我想也许字符串文字在传递给
sizeof
之前转换为指针,导致sizeof(char*)
为4。
I tried replacing STRING
and ""
by char arrays... 我尝试用char数组替换
STRING
和""
char x[] = "";
char y[] = "a string";
int a = sizeof(argc > 1 ? x : y);
... but I got the same results (a=4, b=9, c=1). ...但我得到了相同的结果(a = 4,b = 9,c = 1)。
Then I tried to dive into the C99 spec , but I did not find any obvious explanation in it. 然后我试着深入研究C99规范 ,但我没有找到任何明显的解释。 Out of curiosity I also tried changing changing x and y to other types:
出于好奇,我也尝试将x和y更改为其他类型:
char
and long long int
: a becomes 8 char
和long long int
:a变为8 short
or both char
: a becomes 4 short
或两个char
:a变为4 So there's definitely some sort of conversion going on, but I struggle to find any official explanation. 所以肯定会有某种转换,但我很难找到任何官方解释。 I can sort of imagine that this would happen with arithmetic types (I'm vaguely aware there's plenty of promotions going on when those are involved), but I don't see why a string literal returned by a ternary expression would be converted to something of size 4 .
我可以想象这会发生在算术类型上(我隐约意识到当涉及这些时会有大量的促销活动),但是我不明白为什么三元表达式返回的字符串文字会被转换为某种东西4号 。
NB: on this machine sizeof(int) == sizeof(foo*) == 4
. 注意:在这台机器上
sizeof(int) == sizeof(foo*) == 4
。
Thanks for the pointers guys. 感谢指点家伙。 Understanding how
sizeof
and ?:
work actually led me to try a few more type mashups and see how the compiler reacted. 了解
sizeof
和?:
work实际上是如何让我尝试更多类型的mashup并看看编译器如何反应。 I'm editing them in for completeness' sake: 为了完整起见,我正在编辑它们:
foo* x = NULL; /* or foo x[] = {} */
int y = 0; /* or any integer type */
int a = sizeof(argc > 1 ? x : y);
Yields warning: pointer/integer type mismatch in conditional expression [enabled by default]
, and a == sizeof(foo*)
. 产生
warning: pointer/integer type mismatch in conditional expression [enabled by default]
,以及a == sizeof(foo*)
。
With foo x[], bar y[]
, foo* x, bar* y
or foo* x, bar y[]
, the warning becomes pointer type mismatch
. 使用
foo x[], bar y[]
, foo* x, bar* y
或foo* x, bar y[]
,警告变为pointer type mismatch
。 No warning when using a void*
. 使用
void*
时没有警告。
float x = 0; /* or any floating-point type */
int y = 0; /* or any integer type */
int a = sizeof(argc > 1 ? x : y);
Yields no warning, and a == sizeof(x)
(that is, the floating-point type). 不产生警告,并且
a == sizeof(x)
(即浮点类型)。
float x = 0; /* or any floating-point type */
foo* y = NULL; /* or foo y[] = {} */
int a = sizeof(argc > 1 ? x : y);
Yields error: type mismatch in conditional expression
. 收益率
error: type mismatch in conditional expression
。
If I ever read the spec completely I'll make sure to edit this question to point to the relevant parts. 如果我完全阅读了规范,我将确保编辑此问题以指向相关部分。
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
. 对于表达式
e
, sizeof e
是表达式e
的值的类型的大小。
The expression a ? b : c
表达
a ? b : c
a ? b : c
has a type. a ? b : c
有一种类型。 The type is the common type of the two operand expressions b
and c
. 类型是两个操作数表达式
b
和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). 在您的示例中,
char[9]
和char[1]
的常见类型是char *
(两个数组值表达式都衰减为指向第一个元素的指针)。 (In C++, the rules for string literals are different and there is a const
everywhere.) (在C ++中,字符串文字的规则是不同的,并且到处都有一个
const
。)
You need to understand that sizeof
is entirely a compile-time operator. 您需要了解
sizeof
完全是编译 sizeof
算符。 With VLA it could return a variable expression, otherwise it is a compile-time constant. 使用VLA,它可以返回变量表达式,否则它是一个编译时常量。
What matters is the type of its argument. 重要的是它的论点类型。
So in sizeof(argc > 1 ? STRING : "")
the condition is not evaluated. 所以在
sizeof(argc > 1 ? STRING : "")
, 不评估条件。 The type of the argument is decayed to const char*
. 参数的类型被衰减为
const char*
。 And on your machine, it is 4. 在你的机器上,它是4。
You should code instead (argc > 1)?sizeof(STRING):1
您应该编写代码
(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 由于
STRING
被宏扩展为"a string"
字面值,因此sizeof(STRING)
为9,几乎就像你声明的那样
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. STRING
和""
分别是char[9]
和char[1]
类型的数组对象。 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. 在C语言中,当在表达式中使用数组对象时,它们几乎在所有上下文中都被隐式转换(衰减)为指针类型,几乎没有众所周知的特定异常。
One of such exceptions is sizeof
operator. 其中一个例外是
sizeof
运算符。 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. 当您使用数组对象作为
sizeof
的立即操作数时,该数组对象不会衰减为指针类型,并且您将获得整个数组的大小(以字节为单位)。 This is why sizeof(STRING)
is equivalent to sizeof(char[9])
and evaluates to 9
. 这就是
sizeof(STRING)
等于sizeof(char[9])
并计算为9
。 And sizeof("")
is equivalent to sizeof(char[1])
and evaluates to 1
. 而
sizeof("")
相当于sizeof(char[1])
并且计算结果为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 *)
. 这意味着你的
sizeof(argc > 1 ? STRING : "")
相当于sizeof(argc > 1 ? (char *) STRING : (char *) "")
,并且相当于sizeof(char *)
。 This evaluates to pointer size on your platform, which just happens to be 4
. 这将评估您平台上的指针大小,恰好是
4
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.