C语言的一个问题,如:j=5 求 q=(++j)+(++j)+(++j) ?
voidmain(){inti=5,j=5,p,q;p=(i++)+(i++)+(i++);q=(++j)+(++j)+(++j);printf("%d,%d,%d,%d...
void main(){
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
printf("%d,%d,%d,%d",p,q,i,j);
}这个程序中,对P=(i++)+(i++)+(i++)应理解为三个i相加,故P值为15。然后i再自增1三次相当于加3故i的最后值为8。而对于q 的值则不然,q=(++j)+(++j)+(++j)应理解为q先自增1,再参与运算,由于q自增1三次后值为8,三个8相加的和为24,j的最后值仍为8。理论的计算结果:15,24,8,8实际的输出结果:15,22,8,8为什么? 展开
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
printf("%d,%d,%d,%d",p,q,i,j);
}这个程序中,对P=(i++)+(i++)+(i++)应理解为三个i相加,故P值为15。然后i再自增1三次相当于加3故i的最后值为8。而对于q 的值则不然,q=(++j)+(++j)+(++j)应理解为q先自增1,再参与运算,由于q自增1三次后值为8,三个8相加的和为24,j的最后值仍为8。理论的计算结果:15,24,8,8实际的输出结果:15,22,8,8为什么? 展开
2013-11-26
展开全部
4.2 使用我的编译器,下面的代码 int i=7; printf("%d\n", i++ * i++); 返回 49?不管按什么顺序计算, 难道不该打印出56吗?
尽管后缀自加和后缀自减操作符 ++ 和 -- 在输出其旧值之后 才会执行运算, 但这里的``之后"常常被误解。没有任何保证 确保自增或 自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进 行。也不能保证变量的更新会在表达式 ``完成" (按照 ANSI C 的术语, 在下一个 ``序列点" 之前, 参见问题 3.7) 之前的某个时刻进行。 本例中, 编译器选择使用变量的旧值相乘以后再对二者进行自增运算。
包含多个不确定的副作用的代码的行为总是被认为未定义。(简单而言, ``多个不确定副作用" 是指在同一个表达式中使用导致同一对象修改两 次或修改以后又被引用的自增, 自减和赋值操作符的任何组合。这是一 个粗略的定义; 严格的定义参见问题 3.7, ``未定义" 的含义 参见问题 11.32。) 甚至都不要试图探究这些东西在你的编译 器中是如何实现的 (这与许多 C 教科书上的弱智练习正好相反); 正如 K&R 明智地指出, ``如果你不知道它们在不同的机器上如何实现, 这样的无知可能恰恰会有助于保护你。begintex2html_deferred
参考资料: [K&R1, Sec. 2.12 p. 50]; [K&R2, Sec. 2.12 p. 54]; [ISO, Sec. 6.3]; [H&S, Sec. 7.12 pp. 227-9]; [CT&P, Sec. 3.7 p. 47]; [PCS, Sec. 9.5 pp. 120-1]。
4.7 我怎样才能理解复杂表达式?``序列点" 是什么?
序列点是一个时间点(在整个表达式全部计算完毕之后或在 ||、 &&、 ? : 或逗号 运算符处, 或在函数调用之前), 此刻尘埃落定, 所有的副作用都已确保结束。 ANSI/ISO C 标准这样描述:
在上一个和下一个序列点之间, 一个对象所保存的值至多只能被表达式的 计算修改一次。而且前一个值只能用于决定将要保存的值。
第二句话比较费解。它说在一个表达式中如果某个对象需要写入, 则在同一表达式中对该对象的访问应该只局限于直接用于计算将要 写入的值。这条规则有效地限制了只有能确保在修改之前才访问 变量的表达式为合法。例如 i = i+1 合法, 而 a[i] = i++ 则非法 (参见问题 3.1)。
参见下边的问题 3.8。
参考资料: [ISO, Sec. 5.1.2.3, Sec. 6.3, Sec. 6.6, Annex C]; [Rationale, Sec. 2.1.2.3]; [H&S, Sec. 7.12.1 pp. 228-9]。
12.32 人们好像有些在意实现定义 (implementation-defin-ed)、未明确 (unspecified) 和无定义 (undefined) 行为的区别。它们的区别到底在哪里?
简单地说: 实现定义意味着实现必须选择某种行为并提供文档。 未明确意味着实现必须选择某种行为但不必提供文档。 未定义意味着任何事情都可能发生。标准在任何情况下都不强加需求; 前两种情况下, 它有时建议一组可能的行为 (也可能要求从中选择一种)。
注意既然标准对无定义行为没有强制要求, 编译器就绝对可以做 任何事情。特别地, 对程序其它部分的正常运行没有任何保证; 参见问题 3.2, 有一个相对简单的例子。
如果你对书写可移植代码有兴趣, 你可以忽略它们的区别, 因为通常你都 希望避免依赖三种行为中的任何一种。
参见问题 3.8 和 11.34。
第四种不那么严格定义的行为是 ``场景特定" (locale-specific)。
参考资料: [ISO, Sec. 3.10, Sec. 3.16, Sec. 3.17]; [Rationale, Sec. 1.6]。
12.34 我很吃惊, ANSI 标准竟然有那么多没有定义的东西。 标准的唯一任务不就是让这些东西标准化吗?
某些构造随编译器和硬件的实现而变化, 这一直是 C 语言的一个特点。 这种有意的不严格规定可以让编译器生成效率更高的代码, 而不必让所有 程序为了不合理的情况承担额外的负担。因此, 标准只是把现存的实践 整理成文。
编程语言标准可以看作是语言使用者和编译器实现者之间的协议。协议的 一部分是编译器实现者同意提供, 用户可以使用的功能。而其它部分则包 括用户同意遵守, 编译器实现者认为会被最受的规则。只要双方都恪守 自己的保证, 程序就可以正确运行。如果任何一方违背它的诺言, 则结果 肯定失败。
参见问题 11.35。
参考资料: [Rationale, Sec. 1.1]。
12.35 有人说 i = i++ 的行为是未定义的, 但是我刚在一个兼容 ANSI 的编译器上测试, 得到了我希望的结果。
面对未定义行为的时候, 包括范围内的实现定义行为和未确定行为, 编译器 可以做任何实现, 其中也包括你所有期望的结果。但是依靠这个实现却不明智。 参加问题 7.4, 11.31, 11.32 和 11.34。
尽管后缀自加和后缀自减操作符 ++ 和 -- 在输出其旧值之后 才会执行运算, 但这里的``之后"常常被误解。没有任何保证 确保自增或 自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进 行。也不能保证变量的更新会在表达式 ``完成" (按照 ANSI C 的术语, 在下一个 ``序列点" 之前, 参见问题 3.7) 之前的某个时刻进行。 本例中, 编译器选择使用变量的旧值相乘以后再对二者进行自增运算。
包含多个不确定的副作用的代码的行为总是被认为未定义。(简单而言, ``多个不确定副作用" 是指在同一个表达式中使用导致同一对象修改两 次或修改以后又被引用的自增, 自减和赋值操作符的任何组合。这是一 个粗略的定义; 严格的定义参见问题 3.7, ``未定义" 的含义 参见问题 11.32。) 甚至都不要试图探究这些东西在你的编译 器中是如何实现的 (这与许多 C 教科书上的弱智练习正好相反); 正如 K&R 明智地指出, ``如果你不知道它们在不同的机器上如何实现, 这样的无知可能恰恰会有助于保护你。begintex2html_deferred
参考资料: [K&R1, Sec. 2.12 p. 50]; [K&R2, Sec. 2.12 p. 54]; [ISO, Sec. 6.3]; [H&S, Sec. 7.12 pp. 227-9]; [CT&P, Sec. 3.7 p. 47]; [PCS, Sec. 9.5 pp. 120-1]。
4.7 我怎样才能理解复杂表达式?``序列点" 是什么?
序列点是一个时间点(在整个表达式全部计算完毕之后或在 ||、 &&、 ? : 或逗号 运算符处, 或在函数调用之前), 此刻尘埃落定, 所有的副作用都已确保结束。 ANSI/ISO C 标准这样描述:
在上一个和下一个序列点之间, 一个对象所保存的值至多只能被表达式的 计算修改一次。而且前一个值只能用于决定将要保存的值。
第二句话比较费解。它说在一个表达式中如果某个对象需要写入, 则在同一表达式中对该对象的访问应该只局限于直接用于计算将要 写入的值。这条规则有效地限制了只有能确保在修改之前才访问 变量的表达式为合法。例如 i = i+1 合法, 而 a[i] = i++ 则非法 (参见问题 3.1)。
参见下边的问题 3.8。
参考资料: [ISO, Sec. 5.1.2.3, Sec. 6.3, Sec. 6.6, Annex C]; [Rationale, Sec. 2.1.2.3]; [H&S, Sec. 7.12.1 pp. 228-9]。
12.32 人们好像有些在意实现定义 (implementation-defin-ed)、未明确 (unspecified) 和无定义 (undefined) 行为的区别。它们的区别到底在哪里?
简单地说: 实现定义意味着实现必须选择某种行为并提供文档。 未明确意味着实现必须选择某种行为但不必提供文档。 未定义意味着任何事情都可能发生。标准在任何情况下都不强加需求; 前两种情况下, 它有时建议一组可能的行为 (也可能要求从中选择一种)。
注意既然标准对无定义行为没有强制要求, 编译器就绝对可以做 任何事情。特别地, 对程序其它部分的正常运行没有任何保证; 参见问题 3.2, 有一个相对简单的例子。
如果你对书写可移植代码有兴趣, 你可以忽略它们的区别, 因为通常你都 希望避免依赖三种行为中的任何一种。
参见问题 3.8 和 11.34。
第四种不那么严格定义的行为是 ``场景特定" (locale-specific)。
参考资料: [ISO, Sec. 3.10, Sec. 3.16, Sec. 3.17]; [Rationale, Sec. 1.6]。
12.34 我很吃惊, ANSI 标准竟然有那么多没有定义的东西。 标准的唯一任务不就是让这些东西标准化吗?
某些构造随编译器和硬件的实现而变化, 这一直是 C 语言的一个特点。 这种有意的不严格规定可以让编译器生成效率更高的代码, 而不必让所有 程序为了不合理的情况承担额外的负担。因此, 标准只是把现存的实践 整理成文。
编程语言标准可以看作是语言使用者和编译器实现者之间的协议。协议的 一部分是编译器实现者同意提供, 用户可以使用的功能。而其它部分则包 括用户同意遵守, 编译器实现者认为会被最受的规则。只要双方都恪守 自己的保证, 程序就可以正确运行。如果任何一方违背它的诺言, 则结果 肯定失败。
参见问题 11.35。
参考资料: [Rationale, Sec. 1.1]。
12.35 有人说 i = i++ 的行为是未定义的, 但是我刚在一个兼容 ANSI 的编译器上测试, 得到了我希望的结果。
面对未定义行为的时候, 包括范围内的实现定义行为和未确定行为, 编译器 可以做任何实现, 其中也包括你所有期望的结果。但是依靠这个实现却不明智。 参加问题 7.4, 11.31, 11.32 和 11.34。
2013-11-26
展开全部
你是在visual c++环境调试的,如果在Turbo c中调试则是上面的结果在visual c++环境下,两个++i符合你的结论,但三个以上就不一样了是7+7+8=22
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2013-11-26
展开全部
不同的编译器得出的结果可能不一样的
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询