C 使用数组时后缀/前缀如何工作

C 使用数组时后缀/前缀如何工作,c,C,下面是两个代码示例: int k,j=1; int x[4]={5,14,25,47}; k = x[j] + ++j; printf("%d, %d",j,k); 将显示一条警告—“j”上的操作可能未定义” 但是输出是:2,16 然后我试了一下: int k,j=1; int x[4]={5,14,25,47}; k = x[j] +++j; printf("%d, %d",j,k); 这不会给出任何警告,但输出有点混乱。产出-1,15 为什么在第二

下面是两个代码示例:

int k,j=1;
int x[4]={5,14,25,47};
k = x[j] + ++j;
printf("%d, %d",j,k);
将显示一条警告—“j”上的操作可能未定义” 但是输出是:2,16

然后我试了一下:

int k,j=1;
int x[4]={5,14,25,47};
k = x[j] +++j;
printf("%d, %d",j,k);
这不会给出任何警告,但输出有点混乱。产出-1,15 为什么在第二种情况下j没有增加

k = x[j] +++j;

k = (x[j]++) +j;
另外,
k=x[j]+++j
是未定义的行为,因为加法的求值顺序未定义。除了允许编译器生成任何内容之外,这两个代码段都是对这一行的合理解释:

j++;
k = x[j] + j;

一般来说,避免“聪明”。如果您不能100%确定自己在做什么,请不要在更复杂的语句中使用
++
--
。在之前或之后在单独的行上执行递增或递减。那会帮你省去很多麻烦。例如,你能毫无疑问地在谷歌上准确地说什么吗

while(*str++) { 
    /* Do something */ 
} 
意味着什么?我觉得这更清楚

while(*str) { 
    str++; 
    /* Do something */ 
} 
当然它需要一条线,减少线的数量可能是一件好事,但在这种情况下,我认为最好是安全起见。在这个特殊的例子中,你也可以用括号把它弄清楚:
*(str++)
,如果你愿意的话,但我想你明白我的意思了


我实际上回答了实际的问题:

一个C程序被解析为一个令牌序列,比如
int
+
+
,和
->
。当源文本包含
++
时,这可能是标记
++
++
或标记
++
++
。C 2018第6.4节中的一条规则告诉我们:

如果输入流已解析为预处理令牌(最多可达给定字符),则下一个预处理令牌是可构成预处理令牌的最长字符序列


因此,在
++
中,下一个可能是最长的令牌是
++
,因此取下该令牌,留下
++
作为下一个令牌。So
x[j]+++j被解析为
x
[
j
+
+

注意,第一个代码片段中的语句调用了未定义的行为:
k=x[j]+++j
在没有中间序列点的情况下使用和更新
j
while(*str) { 
    str++; 
    /* Do something */ 
}