教程点上的"C mock tests"是否正确?

  • 本文关键字:是否 tests 教程 mock c c89
  • 更新时间 :
  • 英文 :


因为我已经编写了 C 语言 20 多年,我认为是时候参加测试了!看看我是否学到了什么,或者我是否只是一些欺诈性发布免费但不正确的建议给互联网上的初学者。

这个网站(我不隶属)提供免费的C测试。 https://www.tutorialspoint.com/cprogramming/cprogramming_mock_test.htm。

我参加了测试 1,但以 34 分中的 50 分失败了!是这样吗?我必须放弃我的C程序员生涯吗?这个教程点网站及其测试有多好?

具体来说,我未能回答 Q7、Q9、Q10、Q14、Q16、Q17、Q19、Q21、Q27、Q28、Q31、Q32、Q33、Q35、Q38、Q46 以及测试预期的答案。这些问题的正确答案是什么?

此外,当我在符合 C 编译器 (gcc -std=c11 -pedantic-errors) 上编译问题时,它们都不会通过编译。为什么?我和/或我的编译器坏了吗?还是这个网站一点都不是很好?

这个网站一点也不好。

这些问题是为1999年撤回的C语言的旧版本编写的。它允许您将 main 编写为没有返回类型的main()。这已经不是有效的 C 超过 20 年了,所以这就是它不编译的原因。您需要使用-std=c90进行编译。

虽然在旧的 C90 中,在main()之前隐式 int,操作系统将使用函数 main() 的返回值,所以如果没有像这些例子中那样的 return 语句,这意味着未定义的行为 (C11 6.9.1/12)。

值得注意的是,整个测试也受到printf缺乏n的影响,这意味着stdout在程序结束之前不会被刷新。C 保证在程序终止时刷新它。

具体来说,这些问题也是不正确的:

  • Q7:没有一个答案可能是正确的。操作数'A'255int类型,所以加法(假设A=65)保证不会溢出,而是导致65 + 255 = 320。然后,通过简单赋值将生成的int转换为charc类型。这反过来可能是有符号或无符号的类型,具体取决于编译器。这会影响转换是按照 C11 6.3.1.3/2 明确定义的还是根据 6.3.1.3/3 定义的实现。一个可能的结果是 320 = 140h,截断:40h = 64。这将在适用于 Linux 的 gcc x86 编译器上打印字符'@'

  • 问题 9:代码会导致编译器错误,因为它是违反简单赋值(引用)规则的约束。他们可能打算编写unsigned x = 5, *y=&x, *p = y+0;在这种情况下,结果是未指定的 - 不能保证表达式*y=&x在表达式*p = y+0之前被计算。参见C11 6.7.9/23:

    初始化列表表达式的计算顺序不确定如下: 相互尊重,因此任何副作用发生的顺序是 未指定。

    所以无论你怎么说,整个问题从根本上都是错误的。

  • Q10: 关于是否投malloc的结果,可能会提出很多风格问题。但除此之外,假设#include <stdlib.h>存在,代码就可以了。如果包含不存在(如问题中所示),则代码被破坏,任何事情都可能发生。

  • Q14:这是一个无限循环,无限打印"Hello"。它不打印"无限循环"。

  • 问题
  • 16:请参阅问题 14。此外,一个体面的编译器(如gcc -Wall)可能会在这里抛出一些诊断消息,所以回答"编译错误"不一定是错误的。取决于编译器设置。

  • Q17:假设 2 的补码计算机,则 -2。从理论上讲,它可以打印-1或-2或-(大数字),这取决于计算机是否使用一个补码,两个补码或有符号量级。

  • 问题 19:正确答案是编译器错误。再次因为简单分配的限制。

  • Q21:假设65'A'的符号表值,那么它可以打印'A'(小端序)或0对应的符号(大端序)。后者很可能看起来像"垃圾"。

  • Q27: 正确答案是 strcmp 函数的使用无效,因为缺少#include <string.h>。否则,它将打印 0。

  • 问题 28:编译错误。有趣的是测试是多么不一致。在这里,它突然不允许从整数到指针的隐式转换,它之前愉快地(并且不正确地)允许。

  • Q31: B 或 C 甚至 D。这取决于 int 的大小,几乎可以肯定是 2 或 4。但是,编译器可以自由地在联合末尾添加填充,因此它最好打印更大的数字。

  • Q32: 正确答案确实取决于编译器,但是...为什么哦,为什么它不依赖于Q31中的编译器?

  • Q33: C 允许我们编写shortshort intint short- 都是等价的,所以这个问题没有多大意义。

  • 问题 35:由于代码无法编译,因此没有输出。

  • 问题 38:输出是 7,而不是 6。

  • 问题 46:仅分配了联合的字符成员,其余成员包含不确定的值。联合成员 x 声明为具有自动存储持续时间,并且永远不会占用其地址,因此访问它是未定义的行为。https://stackoverflow.com/a/40674888/584518

    如果不是这样,它会尝试打印一些不确定的值("垃圾")甚至 65 或 0,具体取决于 CPU 字节序。

我对 TutorialsPoint 的 C 模拟测试 #1 中显示的代码有很多保留意见。 使用对 C99 无效的代码,更不用说 C11 或 C17,这很奇怪。 上个千年的代码不应该继续教给新的程序员——除非作为语言自首次标准化以来如何变化的对象课程。

这个SO问题最初讨论了模拟测试的第3问题,但SO问题和主要答案后来被修改,删除了对该问题的注释。

Q3 的代码是:

#include<stdio.h>
main() 
{ 
char s[]="hello", t[]="hello";

if(s==t){
printf("eqaul strings");
}
}

数组st必须位于不同的位置;它们是单独的数组,由相同的字符串初始化,但仍然是单独的数组,因此存储在不同的地址。 条件比较存储数组的地址(字符串比较将使用strcmp()或等效项),并且数组存储在单独的地址,因此比较的结果为 false。

  • 因此,唯一正确的答案是 C — 无输出。
  • 这是TutorialsPoint在他们的密钥中给出的答案。

有一些关于字符串文字的SO以及它们可以存储在同一位置的事实的讨论。 然而,这种讨论是错误的。它不适用于此代码。 用于初始化数组的字符串可以共置,但数组本身不能共置。 但是,假设定义是指针,而不是数组:

char *s = "hello", *t = "hello";

现在,st很可能包含相同的地址,尽管它们也可能包含不同的地址。(st的地址必须不同;它们是两个单独的指针变量)。

但是问题代码中的数组初始值设定项必须初始化两个单独的数组,并且这些单独的数组必须存储在不同的地址,因此问题中的比较s == t必须为 false,因此不会打印任何内容。

最新更新