如何不写代码

图片


准备深入研究勇敢的编程世界了吗? 是否想看几行简单的代码如何表现出不可预测的效果?


如果您的回答是“是的!” -欢迎来到猫。


您会在C或C ++中找到一些有趣的任务。


正确的答案和解释将始终隐藏在扰流板下方。


祝你好运


关于最短的程序


main; 

如果使用C语言编译器编译该程序会怎样?


  1. 未编译。
  2. 未链接。
  3. 编译并链接。

答案是:

这是有效的C代码。
怎么了 在C语言中,您可以省略函数的返回类型,并且在声明变量时,默认情况下它将为int。 而且在C语言中,链接期间函数和全局变量之间没有区别。 在这种情况下,链接器认为main名称下是一个函数。


关于叉子


 #include <iostream> #include <unistd.h> int main() { for(auto i = 0; i < 1000; i++) std::cout << "Hello world!\n"; fork(); } 

Hello World!将被打印多少次?


  1. 1000
  2. 少一点
  3. 更多

答案是:

IO操作被缓冲以提高性能。
调用fork()将产生一个新进程,该进程具有写时复制重复的地址空间。
缓冲线将在每个过程中打印。


关于索引


 #include <iostream> int main() { int array[] = { 1, 2, 3 }; std::cout << (4, (1, 2)[array]) << std::endl; } 

此代码将打印什么?


  1. 1个
  2. 2
  3. 3
  4. 4
  5. 编译错误
  6. 未按标准定义。

答案是:

Porgram打印3。
为什么这样
首先,看一下索引: array[index] == *(array + index) == *(index + array) == index[array]
接下来,我们要处理二进制逗号运算符。 它舍弃其left参数,并返回right的值。


关于正则表达式


 #include <regex> #include <iostream> int main() { std::regex re { "(.*|.*)*O" }; std::string str { "0123456789" }; std::cout << std::regex_match(str, re); return 0; } 

这个常规赛最短时间是什么?


  1. 〜1毫秒
  2. 〜100毫秒
  3. 〜1秒
  4. 〜1分钟
  5. 大约1个小时。
  6. 〜1年。
  7. 宇宙寿命更长。

答案是:

哈哈 没猜到。 取决于编译器。
在我的笔记本电脑上,叮当声显示大约100毫秒的结果。
GCC 57秒! 一分钟! 真的吗?
为什么这样
有两种实现正则表达式的方法。
一种是将正则表达式转换为O(n**2)的状态机,以获取长度为n个字符的正则表达式。
与m个字符的字符串匹配的难度为O(m) 。 这样的正则表达式不支持回溯。
第二个是带有深度搜索的贪婪搜索。 支持回溯。
但是,STL中正则表达式操作的复杂性根本没有定义。 他们在一分钟之内就做好了。


关于Move和Lambda


 #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(Foo&&) { std::cout << "Foo(Foo&&)\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } }; int main() { Foo f; auto a = [f = std::move(f)]() { return std::move(f); }; Foo f2(a()); return 0; } 

程序最后打印到哪一行?


  1. Foo()
  2. Foo(Foo&&)
  3. Foo(const Foo&)

答案是:

Foo(const Foo&) 。 默认情况下,lambda是免疫的。 const隐式添加到[]指定的所有值。
这使lambda的行为类似于正常函数。 对于相同的参数,返回相同的值。
在这种情况下会发生什么? 当我们尝试从函数中移动出f ,我们得到const Foo&&
这是非常奇怪的事情,编译器不知道如何使用它并复制Foo 。 您可以通过声明可变的lambda来解决此问题:


 auto a = [f = std::move(f)]() mutable { return std::move(f); }; 

或者从Foo(const Foo&&)构造一个构造Foo(const Foo&&)


关于x和bar


 #include <iostream> int x = 0; int bar(int(x)); int main() { std::cout << bar; } 

如果您尝试编译并运行此命令会发生什么?


  1. 将打印0
  2. 将打印1
  3. 将打印0x0
  4. 未编译
  5. 未连结

答案是:

程序将打印1
为什么这样
int bar(int(x)); 是一个函数声明,它等效于int bar(int x);
如果要进行类型转换,则需要这样写: int bar((int(x)));
然后我们尝试输出函数的地址,它将被隐式转换为bool,函数的地址不能为零,即 true
不使用bar()函数。 因此,链接时将没有未引用的符号。


关于内联


 #include <iostream> inline size_t factorial(size_t n) { if (n == 0) return 1; return n * factorial(n - 1); } int main() { std::cout << factorial(5) << std::endl; } 

程序编译和链接没有错误,例如g++ -c main.cpp -o main.o && g++ foo.cpp -o foo.o && g++ foo.o main.o -o test 。 如果运行它会怎样?


  1. 将打印120。
  2. 什么都可能发生。

答案是:

什么都可能发生。 这是C ++。
单词inline的所有内容。 这只是对编译器的指示。
它可以简单地将此函数编译为目标文件(最有可能的是将其用于递归函数)。
链接器可以丢弃代码中未内置的内联函数的重复项。
通常出现在第一个文件中的结果文件是在第一个目标文件中找到的结果文件。
如果在foo.cpp中,程序将输出0


 #include <cstddef> inline size_t factorial(size_t n) { if (n == 0) return 0; return 2 * n * factorial(n - 1); } int foo(size_t n) { return factorial(n); } 

关于设计师


 #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } Foo(int) { std::cout << "Foo(int)\n"; } Foo(int, int) { std::cout << "Foo(int, int)\n"; } Foo(const Foo&, int) { std::cout << "Foo(const Foo&, int)\n"; } Foo(int, const Foo&) { std::cout << "Foo(int, const Foo&)\n"; } }; void f(Foo) {} struct Bar { int i, j; Bar() { f(Foo(i, j)); f(Foo(i)); Foo(i, j); Foo(i); Foo(i, j); } }; int main() { Bar(); } 

哪一行最后打印?


  1. Foo(int, int)
  2. Foo(const Foo&, int)
  3. Foo(int, const Foo&)
  4. Foo(int)

答案是:

最后一行是Foo(const Foo&, int)
Foo(i)是变量的声明,它等效于Foo i ,这意味着类i的字段将从作用域中消失。


结论


希望您再也看不到真实的代码。

Source: https://habr.com/ru/post/zh-CN413697/


All Articles