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

Pen*_*lec 13 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;
}
Run Code Online (Sandbox Code Playgroud)

在此示例中(使用gcc 4.4.3和4.7.2进行测试,编译时-std=c99),b为9(8个字符+隐式'\0'),c为1(隐式'\0').a,出于某种原因,是4.

根据argc是否大于1,我希望a为9或1.我想也许字符串文字在被传递到之前转换为指针sizeof,导致sizeof(char*)为4.

我尝试替换STRING""char数组...

char x[] = "";
char y[] = "a string";
int a = sizeof(argc > 1 ? x : y);
Run Code Online (Sandbox Code Playgroud)

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

然后我试着深入研究C99规范,但我没有找到任何明显的解释.出于好奇,我也尝试将x和y更改为其他类型:

  • char并且long long int:a变为8
  • 两者short或两者char:a变为4

所以肯定会有某种转换,但我很难找到任何官方解释.我可以想象这会发生在算术类型上(我隐约意识到当涉及这些时会有大量的促销活动),但是我不明白为什么三元表达式返回的字符串文字会被转换为某种东西4号.

注意:在这台机器上sizeof(int) == sizeof(foo*) == 4.

跟进

感谢指点家伙.理解如何sizeof?:工作实际上让我尝试了一些类型mashup并看看编译器如何反应.为了完整起见,我正在编辑它们:

foo* x = NULL; /* or foo x[] = {} */
int  y = 0;    /* or any integer type */

int a = sizeof(argc > 1 ? x : y);
Run Code Online (Sandbox Code Playgroud)

收益率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);
Run Code Online (Sandbox Code Playgroud)

不产生警告,a == sizeof(x)(即浮点类型).

float x = 0;    /* or any floating-point type */
foo*  y = NULL; /* or foo y[] = {} */

int a = sizeof(argc > 1 ? x : y);
Run Code Online (Sandbox Code Playgroud)

收益率error: type mismatch in conditional expression.

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

Ker*_* SB 15

您必须了解表达式,这是该语言的核心组件.

每个表达式都有一个类型.对于表达式e,sizeof e是表达式值的类型的大小e.

表达式a ? b : c有一个类型.类型是普通类型两个操作数的表达式bc.

在你的例子,常见类型char[9]char[1]char *(两者数组值表达式衰变的指针的第一个元素).(在C++中,字符串文字的规则是不同的,并且const到处都有.)

  • @Peniblec这已经在SO @ http://stackoverflow.com/questions/8535226/return-type-of-ternary-conditional-operator上讨论过了 (3认同)

Bas*_*tch 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'};
Run Code Online (Sandbox Code Playgroud)