具有条件(三元)表达式的运算符'sizeof'

时间:2014-07-24 11:42:37

标签: c sizeof conditional-operator

在给出三元表达式时,我很难理解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;
}

在这个例子中(用gcc 4.4.3和4.7.2测试,用-std=c99编译),b是9(8个字符+隐式'\0'),c是1(隐式{{1 }})。 a,出于某种原因, 4

根据argc是否大于1,我希望a为9或1.我想也许字符串文字在传递给'\0'之前转换为指针,导致sizeof到是4。

我尝试用char数组替换sizeof(char*)STRING ...

""

...但我得到了相同的结果(a = 4,b = 9,c = 1)。

然后我试图潜入C99 spec,但我没有找到任何明显的解释。出于好奇,我也尝试将x和y更改为其他类型:

  • char x[] = ""; char y[] = "a string"; int a = sizeof(argc > 1 ? x : y); char:a变为8
  • long long int或两者short:a变为4

所以肯定会有某种转换,但我很难找到任何官方解释。我可以想象这种情况会发生在算术类型上(我很清楚地知道那里有大量的促销活动),但我不明白为什么一个字符串由三元表达式返回的字面值将转换为大小为4的单词

注意:在这台机器上char

后续

感谢指点家伙。了解sizeof(int) == sizeof(foo*) == 4sizeof如何工作实际上让我尝试了更多类型的mashup并看看编译器如何反应。我是为了完整而编辑它们的。缘故:

?:

收益foo* x = NULL; /* or foo x[] = {} */ int y = 0; /* or any integer type */ int a = sizeof(argc > 1 ? x : y); warning: pointer/integer type mismatch in conditional expression [enabled by default]

使用a == sizeof(foo*)foo x[], bar y[]foo* x, bar* y,警告变为foo* x, bar y[]。使用pointer type mismatch时没有警告。

void*

不产生任何警告,float x = 0; /* or any floating-point type */ int y = 0; /* or any integer type */ int a = sizeof(argc > 1 ? x : y); (即浮点类型)。

a == sizeof(x)

收益率float x = 0; /* or any floating-point type */ foo* y = NULL; /* or foo y[] = {} */ int a = sizeof(argc > 1 ? x : y);

如果我完全阅读了规范,我将确保编辑此问题以指向相关部分。

3 个答案:

答案 0 :(得分:16)

您必须了解表达式,它们是该语言的核心组成部分。

每个表达式都有类型。对于表达式esizeof e是表达式e的值类型的大小。

表达式a ? b : c有一个类型。类型是两个操作数表达式bc常用类型

在您的示例中,char[9]char[1]的常见类型是char *(两个数组值表达式都衰减为指向第一个元素的指针)。 (在C ++中,字符串文字的规则是不同的,到处都有const。)

答案 1 :(得分:7)

您需要了解sizeof完全是编译时运算符。 使用VLA,它可以返回一个变量表达式,否则它是一个编译时常量。

重要的是其论点的类型。

因此,sizeof(argc > 1 ? STRING : "")条件评估。参数的类型衰减为const char*。在你的机器上,它是4。

您应该改为代码(argc > 1)?sizeof(STRING):1

由于STRING已宏扩展为"a string"字面值,sizeof(STRING)为9,几乎就像您声明了

const char STRING[] = {'a',' ','s','t','r','i','n','g','\0'};

答案 2 :(得分:2)

STRING""分别是char[9]char[1]类型的数组对象。在C语言中,当在表达式中使用数组对象时,它们几乎在所有上下文中都被隐式转换(衰减)为指针类型,几乎没有众所周知的特定异常。

其中一个例外是sizeof运营商。当您使用数组对象作为sizeof的立即操作数时,数组对象不会衰减为指针类型,并且您将获得整个数组的大小(以字节为单位)。这就是sizeof(STRING)等同于sizeof(char[9])并评估为9的原因。 sizeof("")相当于sizeof(char[1]),评估为1

但是当您使用数组对象作为?:运算符的操作数时,上下文不再是例外。在?:运算符数组的上下文中,立即衰减为指针。这意味着您的sizeof(argc > 1 ? STRING : "")相当于sizeof(argc > 1 ? (char *) STRING : (char *) ""),相当于sizeof(char *)。这将评估您平台上的指针大小,恰好是4