我将参加考试,我的老师会问一些奇怪的C语法规则。像:
int q=5;
for(q=-2;q=-5;q+=3) { //assignment in condition part??
printf("%d",q); //prints -5
break;
}
或者
int d[][3][2]={4,5,6,7,8,9,10,11,12,13,14,15,16};
int i=-1;
int j;
j=d[i++][++i][++i];
printf("%d",j); //prints 4?? why j=d[0][0][0] ?
或
extern int a;
int main() {
do {
do {
printf("%o",a); //prints 12
} while(!1);
} while(0);
return 0;
}
int a=10;
我找不到任何网站或书籍的规则。真是荒谬和不寻常。我在哪里可以找到?
答案 0 :(得分:2)
关于for(q=-2;q=-5;q+=3) {
,您需要做的就是将其分解为其组件。首先运行q=-2
,然后测试q=-5
,如果不是0
(它不是因为它是值为-5
的表达式),那么循环身体运行一次。然后break
强制过早退出无限循环。然后永远不会达到q+=3
的表达式。
d[i++][++i][++i]
的行为未定义。巧妙地告诉你的老师。
"%o"
格式表示八进制输出。 a
的十进制设置为10,八进制为12。如果你写了:
int a=012; // octal constant.
答案 1 :(得分:2)
对我而言,您的老师似乎在问问题是否存在未定义的行为。
如果你告诉他这是不正确的,你就直接面对他了。
但是,您可以执行以下操作:
这样你就不会说他错了,你只是在展示一些事实,而你却表明你愿意学习和工作。
在考试之前做了很长时间,以便教师可以调查并思考他的问题,以便他能及时更改考试。
我找不到任何网站或书籍的规则。我在哪里可以找到?
见Where do I find the current C or C++ standard documents?。如果你在大学有一个好的图书馆,他们应该拥有一份副本。
答案 2 :(得分:1)
C语言标准的online version有你需要的东西(在这个答案中我会指的是);请记住,这是一个语言定义,而不是一个教程,因此对于那些没有很多经验的人来说可能并不容易阅读。
话虽如此,老师却给你扔了几个犯规球。例如:
j=d[i++][++i][++i];
由于多种原因,此语句会导致未定义的行为。上面链接的文件第6.5节的前几段解释了这个问题,但简而言之:
除少数情况外,C不保证对表达式进行从左到右的评估;它也不保证在评估后立即应用副作用;
尝试在序列点 1 之间多次修改对象的值,或者修改然后尝试使用没有插入序列点的对象的值,导致未定义行为。
基本上,不要写任何形式:
x = x++;
x++ * x++;
a[i] = i++;
a[i++] = i;
C不保证从左到右评估每个++i
和i++
,并且不保证每个评估的副作用立即应用。因此j[i++][++i][++i]
的结果没有明确定义,结果将不同于不同的程序,甚至是同一程序 2 的不同构建。
AND ,除此之外,i++
评估i
的当前值;很明显,你的老师的目的是让j[i++][++i][++i]
评估为j[-1][1][2]
,因为你试图在数组边界之外进行索引,所以也会导致未定义的行为。
这就是为什么当教师把这种代码扔给他们的学生时,我讨厌,讨厌,讨厌它 - 不仅是它不必要地混淆,不仅鼓励不好的练习,而且比不是它只是简单的错误。
至于其他问题:
for(q=-2;q=-5;q+=3) { //assignment in condition part??
见6.5.16和6.8.5.3。简而言之,赋值表达式具有一个值(任何类型转换后左操作数的值),它可以作为for
循环中控制表达式的一部分出现。只要赋值的结果非零(如上例所示),循环就会执行。
printf("%o",a); //prints 12
见第7.21.6.1节。 o
转换说明符告诉printf
将整数值格式化为八进制:1010 == 128
<小时/>
&&
,||
和?:
运算符的左操作数之后,序列点出现在语句的末尾,函数参数的评估和函数调用之间,以及其他几个地方。完整清单见附件C.